古人云:胜负兵家之常,善用兵者能因败为成。
内部类分类:
1.实例(成员)内部类
基本格式:
class OuterClass{
///
class InnerClass{
///
}
}
实例内部类和正常类的使用并没有什么大的不同
如何使用:1.
错误使用:InnerClass demo=new InnerClass();
正确使用:OuterClass out=new OuterClass();
OuterClass.InnerClass in=out.new InnerClass();
为什么需要先创建外部类对象呢?顾名思义,实例内部类,相当于外部类的实例成员,当然依赖外部对象。
2.外部类提供访问内部类的接口(更推荐,就像老板和秘书的感觉):
在外部类的内部进行实例内部类的实例化。
注意事项:1.实例内部类中不能有stati修饰的变量或者方法
原因:可以这么理解,假设实例内部类可以定义static修饰的变量或者方法--->
我们知道static修饰的方法或者变量可以直接通过类名.的方式来调用,而内部类
不可以通过这种方式调用,即Out.In.num,因为实例内部类只是class,而未被
static修饰,所以无法再未定义外部类的情况下Out.In的,在这一步就已经断了。
2.(1)外部类和实例内部类的普通变量重名:
优先使用实例内部类的变量
想要访问外部的采用:Out.this.name
(2)外部类的静态变量和实例内部类的普通变量重名:
依然优先使用实例内部类的变量
想要访问外部的采用:Out.name
如果一个内部类,想要不依赖外部对象就可以使用,那就得static出马了
2.静态内部类
即在实例内部类的基础上多了一个static修饰。
我在实例内部类中经常提到它,那么它究竟特殊在哪呢?
使用方法:
不需要先创建外部类对象,就可实例化。
Out.In in=new Out.In();
注意事项:1.和静态方法一样,不能再该类中使用外部类非静态的方法或者变量,因为它不在依赖对象。
3.本地(方法)内部类【不重要】
即外部类方法中定义的类
注意事项:1.该类不可被public等权限修饰符和static修饰
2.类内部不可以使用所在方法中非final修饰的变量【目的:改变变量的生命周期原因:因为方法栈帧时随着方法调用结束而释放,而方法内部类对象是靠jvm回收的,这样就可能出现方法调用结束了对象还在清况】,但是
如果你使用了,也能正常使用,这是jdk的1.8版本后做出的改进,会帮你把那个默认改成final的类型。不过如果你对那个变量进行操作的话,就不会默认了,如图:
就报错了。
3.只可在所在方法内部实例化,如果在方法外实例化就会这样
4.匿名内部类
顾名思义,没有名字的内部类。
使用方法:
1.继承式:
用一个匿名的类继承一个抽象类/类,并重写它的抽象方法/方法;
以抽象类举例,格式:(假设Dog类是抽象类)
Dog dog=new Dog(){
//重写Dog内的方法
}
普通类同上。
这可不是实例化抽象类,希望大家不要弄混了!!!
public class AnonymousClassDemo {
public static void main(String[] args) {
new Outer().test();
}
}
class Outer{
public void test(){
Dog dog=new Dog() {//重点
@Override
protected void eat() {
System.out.println("二狗在干饭");
}
};
dog.eat();
}
}
abstract class Dog{
protected abstract void eat();
}
2.接口式
和继承式大差不差。
格式:假设Cat是接口
Cat cat=new Cat(){
//实现接口Cat内的方法
}
public class AnonymousClassDemo {
public static void main(String[] args) {
new Outer1().test();
}
}
class Outer1{
public void test(){
Cat cat=new Cat() {
@Override
public void run() {
System.out.println("小黑在跑!!");
}
};
cat.run();
}
}
interface Cat{
void run();
}
同样,这可不是实例化接口,希望大家不要弄混了!!!
3.方法参数式:
即在给方法传入参数时使用:
public class AnonymousClassDemo {
public static void main(String[] args) {
new Outer1().test(new Cat() {//传入时使用
@Override
public void run() {
System.out.println("迪奥娜在逃跑!!!");
}
});
}
}
class Outer1{
public void test(Cat cat){
cat.run();
}
}
interface Cat{
void run();
}
注意事项:
1.{}内不能存在构造方法,这个很容易看出来,毕竟匿名内部类没有名字,何来的构造方法呢。
2.匿名内部类中不能定义静态方法和属性。
3.匿名内部类是局部的,所有局部(本地/方法)内部类的限制对他也有效,这也就能解释了第二条了。
4.有且只能使用一次,只能在创建时使用【不过如果你定义在类的属性位置,类的其他地方也能用】。
public class AnonymousClassDemo {
public static void main(String[] args) {
new Outer2().test();
new Outer2().test2();
}
}
class Outer2{
Bird bird=new Bird(){//使其称为Outer2类的一个属性
@Override
public void fly() {
System.out.println("凤飞飞");
}
};
public void test(){
bird.fly();
}
public void test2(){
bird.fly();
}
}
abstract class Bird{
public abstract void fly();
}
内部类的使用
目前我也在学习阶段,没有遇到什么需要内部类的地方,我只能给大家转述一下别人的说法:
我们知道继承只能单继承,内部类也可以继承,这样就可以间接的实现了类的多继承。
那么更推荐哪种类呢?这里推荐静态内部类,主要还是他不依赖对象,不容易出现外部类释放了,内部类还没释放等而导致的内存泄漏
那么内部类就攻略到这里了!!!感谢阅读!