一、位置
成员内部类是最普通的内部类,它定义在一个类的内部
二、内部类的结构
1.可以定义非静态属性和方法,不可以定义static修饰的属性和方法,可以定义static final修饰的编译期变量【不用加载类的字节码】
1.1为什么不可以定义static修饰的属性和方法?
首先内部类是外部类的一个成员,只有当外部类初始化的时候,内部类才能初始化,静态变量属于类级别,在类加载的时候就初始化,
所以两者本身在语法上就有矛盾。
1.2为什么可以定义static final修饰的变量?
首先要先知道sttaic final修饰的变量叫做常量,常量分为编译期常量和非编译期常量
编译期常量:在程序编译阶段【不需要加载类的字节码】,就可以确定常量的值
非编译期常量:在程序运行阶段【需要加载类的字节码】,可以确定常量的值
public class OutterClass { class Inner{ int a = 0;//非静态变量 static int b = 0;//静态变量【报错!!】 static final int c = 0;//编译期常量,不需要类加载 static final Integer d = new Integer(2);//非编译期常量,需要类加载【报错!!】 } public static void main(String[] args) { System.out.println(OutterClass.Inner.b); System.out.println(OutterClass.Inner.c); System.out.println(OutterClass.Inner.d); } }
b属性是静态的,它需要加载类的字节码Inner类,由于它是在OutterClass内部,需要外部类实例化才能加载,但是调用处没有实例化外部类,所以Inner也不会类加载,所以报错!!
c属性是编译期常量,它不需要加载类的字节码Inner类,所以不会报错
d属性是非编译期常量。它需要加载类的字节码Inner类,所以报错!!
2.内部类可以被任何访问修饰符修饰
因为它也是类的成员
三、内部类访问外部类
1.可以访问任何属性和方法【包括私有的、静态的】
访问方式有2种 :直接写属性名或者是外部类.this.属性【方法】
1.1直接写属性名
这种方式有个缺点:如果内部类定义的属性【方法】和外部类一样,会发生隐藏现象,取得的是内部类的值,若想取得外部类的值,采用外部类.this.属性【方法】
1.2若采用直接写属性名获得外部类值,其实本质还是外部类.this.属性
源码:
public class Outter { private int a = 3; class Inner{ public void get(){ System.out.println(a); } } }
反编译后的源码:Outter.class【编译成产生了2个字节码文件Outter.class和Outter$Inner.class】
public class Outter { private int a; public Outter() { this.a = 3; } class Inner { public void get() { System.out.println(Outter.this.a); } } }
四、外部类访问内部类
1.访问普通属性和方法
class Outter { class Inner{ int a = 3; public void get(){ System.out.println("hello"); } } public static void main(String[] args) { Outter.Inner in = new Outter().new Inner(); System.out.println(in.a); in.get(); } }
2.访问常量
class Outter { class Inner{ static final int a = 4; } public static void main(String[] args) { //第一种 Outter.Inner in = new Outter().new Inner(); System.out.println(in.a); //第二种 System.out.println(Outter.Inner.a); } }
以上是我对成员内部类的总结,如果有不对的地方还请指出,大家共同进步!!