一. 静态内部类
如何写一个静态内部类?
class OuterClass{ private int a = 10;//实例数据成员 private int b = 20; private static int c = 30;//静态成员 private static final int d = 40;//被final修饰的静态数据成员,值无法改变 public OuterClass(){//外部类的构造方法 System.out.println("OuterClass() init~~~~"); } public void show(){ System.out.println("OuterClass() show~~~~"); } //通过static修饰,静态内部类 static class InnerClass{ private int data1 = 10; private int data2 = 20; private int c = 100; private static int data3 = 30; public InnerClass(){//内部类的构造方法 System.out.println("InnerClass init~~~~"); } public void show2(){ System.out.println("InnerClass show2()~~~~"); System.out.println("innerclass c:"+c); System.out.println("outerclas c:"+OuterClass.c);//外部类的c是静态的, //通过类名.数据成员来访问 System.out.println("d:"+d); } } }
public class TestDemo2 { //静态内部类 public static void main(String[] args) { //InnerClass in2 = new InnerClass();//不要这样写,会报错! OuterClass.InnerClass in = new OuterClass.InnerClass(); in.show2(); } }
运行结果如图
当在静态内部类里访问外部类的静态数据成员是没有问题的,但是如果访问外部类的实例数据成员时,就会报错。如图
那么静态内部类如何访问外部类的实例成员变量?
1.因为实例成员变量依赖于外部类的对象
2.能否传入一个外部类对象(由构造函数传入)
3.主函数内实例化一个外部类对象OuterClass outer = new OuterClass();
4.在内部类的构造函数传入一个外部类的实例成员变量 OuterClass o2;
5.接收外部类对象o2
6.o2已经拿到了外部类对象
7.System.out.println("a:"+o2.a);
static class InnerClass{ private int data1 = 10; private int data2 = 20; private int c = 100; private static int data3 = 30; OuterClass o2; public InnerClass(OuterClass o){//内部类的构造方法 o2 = o;//通过构造方法传入外部类对象 System.out.println("InnerClass init~~~~"); } public void show2(){ System.out.println("InnerClass show2()~~~~"); //System.out.println("a:"+a);//不可以访问外部类的成员,那怎么访问???? System.out.println("outerclass a:"+o2.a);//通过外部类对象来访问外部类的非静态数据成员 System.out.println("innerclass c:"+c); System.out.println("outerclass c:"+OuterClass.c);//外部类的c是静态的, //通过类名.数据成员来访问 System.out.println("d:"+d); }
public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass in = new OuterClass.InnerClass(outer); in.show2(); }
这样就可以访问外部类的实例数据成员啦
二. 实例内部类
class OuterClass2{ private int data1 = 1000; private int a = 20; private int b = 20; private static int c = 30;//静态成员 private static int d = 40; class InnerClass{//实例内部类,类似实例成员方法,依赖于外部类对象 private int data1 = 10; private int data2 = 20; //private static int data3 = 30;//实例内部类里不能有静态成员方法,会报错 private static final int data4 = 30;//编译时确定的立即数 //private static final int data5 = data1 + 30; //static InnerClass in = new InnerClass(); public void show2(){ System.out.println("InnerClass show2()~~~~"); System.out.println("data1:"+data1);//是内部类的 System.out.println("data1:"+this.data1);//也是内部类的 System.out.println("outer data1:"+OuterClass2.this.data1);//通过这种方法可以访问外部类的数据成员 System.out.println("b:"+b);//可以访问,c和d也可以 } public InnerClass(){ System.out.println("InnerClass init~~~~"); } } public OuterClass2(){ System.out.println("OuterClass() init~~~~"); } public void show(){ System.out.println("OuterClass() show~~~~"); } }
创建实例内部类对象
public static void main(String[] args) { OuterClass2 outer = new OuterClass2(); //实例化一个内部类,依赖于外部类对象 OuterClass2.InnerClass in = outer.new InnerClass(); in.show2(); }
1.为什么实例内部类中必须定义一个编译期间可以确定的立即数
---解释①一个类的初始化过程,先static 再实例方法
---解释②实例内部类的设计意义
-------每一个实例内部类必须有一个外部类对象,依赖外部类对象
假设:static InnerClass in = new InnerClass();成立
OuterClass.InnerClass.in 可以直接拿到实例内部类的一个实例
违背了设计意义(依赖外部类对象),有冲突。
2.实例内部类有没有额外的内存消耗
---有的,还有外层类的this引用变量
三. 本地内部类
在方法内部的类
//本地内部类,在方法内部的类 public void test(){ final int data6 = 10;//局部变量 class InnerClass{ private int a = 10; //private static int b = 20;//报错 private static final int c = 30;//编译期间所确定的立即数 public InnerClass(){ System.out.println("test() InnerClass Init~~~~"); } public void show(){ System.out.println("a: "+a); System.out.println("c: "+c); System.out.println("data6: "+data6); System.out.println("test() show~~~~"); } } InnerClass in = new InnerClass(); in.show(); }
四. 匿名内部类
相当于当前类的子类
public class TestDemo3 { public static void test(Student s){ s.show(); } //匿名内部类,相当于当前类的子类 public static void main(String[] args) { new Student(){ public void show(){ System.out.println("niming show()~~~~"); } }.show(); /* test(new Student(){ public void show(){ System.out.println("niming show()~~~~"); } });*/ }