写这篇文章的原因是自己在Android写适配器的过程中没有新建class,而是采用内部类的写法报错,代码大致抽象成:
问询他人的结果:
iii类实例化时,innerClass还没被实例化,所以报错,类似于静态方法中不能引用非静态的方法和变量。
最开始并没有深入了解,随着我学习的不断深入,可以一言以释之:
静态是优先于对象存在的,随着类的消失而消失,可以被类之间调用,被所有对象共用。
也就是说静态优先被创建,这时非静态可能还没有被创建,所以静态不可以访问非静态。
回到本问题:
内部类的特点如下:
- 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的
.class
文件,但是前面冠以外部类的类名和$
符号。 - 内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否为 private 的。
- 内部类声明成静态的,就不能随便访问外部类的成员变量,仍然是只能访问外部类的静态成员变量。
如果内部类依赖于外部类的对象(非静态内部类):这时内部类就会隐式持有外部类引用,这是因为内部类虽然和外部类写在同一个文件中,但是编译后还是会生成不同的class
文件,其中内部类的构造函数中会传入外部类的实例,然后就可以通过this$0
访问外部类的成员。
//原代码
class InnerClassOutClass{
class InnerUser {
private int age = 20;
}
}
//class代码
class InnerClassOutClass$InnerUser {
private int age;
InnerClassOutClass$InnerUser(InnerClassOutClass var1) {
this.this$0 = var1;
this.age = 20;
}
}
也就是说在内部类中可以调用外部类的方法,变量等等,所以肯定会持有外部类的引用的,该引用是指向创建它的外围类的对象,这个引用意味着:
1.非静态内部类不可以定义静态的属性和方法(不能有静态成员)
2.只有在外部的类被实例化后,这个内部类才能被实例化
如果内部类不依赖于外部类的对象,而是依赖于外部类(静态内部类):
class OutClass{
static class InnerClass {
}
}
它可以不依赖于外部类实例而被实例化.但是它不能像普通内部类一样无限制的访问外部类的方法和成员变量,只能访问静态成员变量和静态方法
将类比喻成鸡蛋,内部类为蛋,,外部类是蛋壳。那么静态类相当于熟鸡蛋,就算蛋壳破碎(外部类没有实例化),蛋黄依然完好(内部类可以实例化);而非静态类相当于生鸡蛋,蛋壳破碎(无实例化),蛋黄也不会独存(不能实例化)。
综上所述:外部类没有实例化时,内部类也不会加载,这时候如果调用内部类的静态成员或方法,内部类没有被加载,却试图在内存中创建该内部类的静态成员,显然矛盾。所以实例内部类不能有静态成员变量或静态方法。