成员内部类
成员内部类又称实例内部类,作为外部类的一个成员存在,与外部类的属性、方法并列。
成员内部类中,不能定义静态成员,可以访问外部类的所有成员,在内部类中访问外部类中与内部类同名的实例变量用外部类名.this.变量名,如果内部类中没有与外部类同名的变量,则可以直接用变量名访问外部类变量。
话不多说,还是在程序中体现以上的要点:
/** 外部类 */
class OuterClass{
//作为外部类的一个成员存在,与外部类的属性、方法并列。
private int data1 = 1000;
private int a = 20;
private static int b = 30;
private static final int d = 40;
public OuterClass(){
System.out.println("OuterClass() init!");
}
public void print(){
System.out.println("OuterClass print()!!" );
}
/** 成员内部类 */
class InnerClass{
// 内部类和外部类的实例变量可以共存
private int data1 = 10;
private int data2 = 20;
//private static int data3 = 30; //成员内部类中不能定义静态成员,详见下面解释
// final修饰的为立即数
private static final int data4 = 30;
//private static final int data5 = data1+30;// 内部类是一个编译时的概念,而data1只有在运行时才能确定
private static final int data6 = data4 + 30; // 立即数
public InnerClass(){
System.out.println("InnerClass() init!!");
}
public void print(){
// 如果内部类中没有与外部类同名的变量,则可以直接用变量名访问外部类变量
System.out.println("a = " + a);
System.out.println("b = " + b);
//在内部类中访问外部类中与内部类同名的实例变量用外部类名.this.变量名
System.out.println("data1 : " + OuterClass.this.data1);
//在内部类中访问内部类自己的变量可以直接变量名,也可以用this.变量名
System.out.println("data2 : " + this.data2);
System.out.println("data2 : " +data2);
}
public void print1() {
System.out.println("这是一个空方法");
}
}
/** 外部类的静态方法访问成员内部类,与在外部类外部访问成员内部类一样 */
public static void outerFun() {
// 先实例化一个内部类对象
OuterClass out = new OuterClass();
// 根据外部类对象建立内部类对象
OuterClass.InnerClass in1 = out.new InnerClass();
// 然后通过内部类对象调用
in1.print1();
}
/** 外部类的非静态方法访问成员内部类 */
public void outerFun1() {
// 先实例化一个内部类对象
InnerClass in2 = new InnerClass();
// 然后通过内部类对象调用
in2.print1();
}
}
/** 主类 */
public class Demo {
public static void main(String[] args) {
// 访问内部类方法
OuterClass outer = new OuterClass();
OuterClass.InnerClass in = outer.new InnerClass();
in.print();
// 访问外部类然后调用内部类方法
outer.outerFun();
outer.outerFun1();
}
}
结果是:
OuterClass() init! // 每次调用类方法时先执行类的构造方法
InnerClass() init!!
a = 20
b = 30
data1 : 1000
data2 : 20
data2 : 20
InnerClass() init!!
这是一个空方法
InnerClass() init!!
这是一个空方法
关于为什么不能在成员内部类中使用static关键字修饰变量或方法的解释
解释一:从static类型的加载过程层面解释
static类型的属性和方法,在类加载的时候就会存在于内存中。而非静态内部类并不随外部类一起加载,只有在实例化外
部类之后才会加载。外部类并没有实例化,内部类还没有加载,此时却试图在内存中创建并调用该内部类的静态成员,这明
显是矛盾的。故成员内部类中不能有静态成员变量或静态方法。
解释二:从成员内部类的设计意义解释:
通过static修饰成为类的方法,使用时用“类名.方法名”的方式就可以调用,相当于定义了一个全局的函数。而内部类的
设计目的是每一个实例内部类必须有一个外部类对象与其对应,内部类依赖与外部类对象。很明显,这两者完全相悖,故内部
类中不能使用static关键字。
关于为什么内部类的成员变量要用final修饰的解释
java类加载顺序,首先加载类,执行static变量初始化,接下来执行对象的创建,如果我们要执行代码中的变量int a
初始化,那么必须先执行加载外部类,再加载内部类,最后初始化静态变量 a ,问题就出在加载内部类上面,我们可以把内部类
看成外部类的非静态成员,它的初始化必须在外部类对象创建后以后进行,要加载内部类必须在实例化外部类之后完成 ,java
虚拟机要求所有的静态变量必须在对象创建之前完成,这样便产生了矛盾。
而java常量放在内存中常量池,它的机制与变量是不同的,编译时,加载常量是不需要加载类的,所以就没有上面那种矛盾。