外部类和内部类其实是2个类,先加载外部类在加载内部类
在Java中内部类主要分为成员内部类(非静态内部类、静态内部类)匿名内部类、局部内部类。成员内部类可以用public、private、protected、default任意进行修饰。
非静态内部类(外部类里使用非静态内部类和平时使用其它类没什么不同)
-
非静态内部类可以直接访问外部类的成员但是外部类不能直接访问非静态内部类成员,可以通过创建静态内部类的对象来访问。
-
非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象,那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象
-
非静态内部类不能有静态方法、静态属性和静态初始化块(就是不能有static的存在)(解释:非static的内部类,在外部类加载的时候,并不会加载它,所以它里面不能有静态变量或者静态方法。1、static类型的属性和方法,在类加载的时候就会存在于内存中。2、要使用某个类的static属性或者方法,那么这个类必须要加载到jvm中。基于以上两点,可以看出,如果一个非static的内部类如果具有static的属性或者方法,那么就会出现一种情况:内部类未加载,但是却试图在内存中创建static的属性和方法,这当然是错误的。原因:类还不存在,但却希望操作它的属性和方法。)
-
外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例
1 package com.testInner; 2 public class TestInner { 3 public static void main(String[] args) { 4 Outer.Inner inner = new Outer().new Inner();//定义一个内部类的对象,内部类对象是依赖外部类对象的,所以得这么创建 5 inner.show(); 6 } 7 } 8 //定义外部类 9 class Outer{ 10 private int age=90; 11 public void run() { 12 System.out.println("Run"); 13 } 14 //定义内部类 15 class Inner{ 16 private int age=10; 17 public void show() { 18 System.out.println("Inner's age is:"+age);//10 19 System.out.println("Outer's age is:"+Outer.this.age);//90 20 int age = 5; 21 System.out.println("Local variable's age is:"+age);//5 22 23 } 24 } 25 }
静态内部类:
-
当一个静态内部类对象存在,并不一定存在对应的外部类对象。因此,静态内部类的实例方法不能直接访问外部类的实例方法。
-
静态内部类看作外部类的一个静态成员。因此,外部类的方法中可以通过“静态内部类.名字”的方式访问静态内部类的静态成员,通过new静态内部类()访问静态内部类的实例
1 package com.testInner; 2 public class TestInner { 3 public static void main(String[] args) { 4 Outer.Inner inner = new Outer().new Inner();//错误, 5 修正:Outer.Inner inner = new Outer.Inner(); 6 inner.show(); 7 } 8 } 9 //定义外部类 10 class Outer{ 11 private int age=90; 12 public void run() { 13 System.out.println("Run"); 14 } 15 //定义内部类 16 static class Inner{ 17 private static int age=10; 18 public void show() { 19 System.out.println("Inner's age is:"+age); 20 System.out.println("Outer's age is:"+Outer.this.age);//错误,不能访问外部类的非static成员 21 int age = 5; 22 System.out.println("Local variable's age is:"+age); 23 24 } 25 } 26 }
匿名内部类:适合那种只需要使用一次的类,比如键盘监听操作等等
语法:
new 父类构造器(实参类表)/实现接口 (){ //匿名内部类的类体 }
Example:
1 package com.testanonymousclass; 2 public class TestAnonymousClass { 3 4 public void a(A a) { 5 System.out.println("#################"); 6 a.aa(); 7 } 8 9 10 public static void main(String args[]) { 11 TestAnonymousClass t = new TestAnonymousClass(); 12 t.a(new A() {//有个没名的类实现了A接口它的类体中实现了aa方法,并且这个没名的类通过new了个对象传给了TestAnonymousClass的a方法 13 public void aa() { 14 System.out.println("I'm the anonymousclass's function."); 15 } 16 }); 17 } 18 } 19 interface A{ 20 public void aa(); 21 }
此处的A是接口,而我们却new了A,那不就是直接实例化接口啦?其实不然,此处代码的意思就是new了一个实现A接口的匿名内部类,然后new得到匿名内部类的对象再向上转型为它实现的接口的类型(原始类型,这里实现A接口的就是该匿名类)。
局部内部类:在方法体中定义一个类,该类的作用域只在这个方法体中。
1 public class Test2{ 2 public void show(){ 3 class Inner{ 4 public void fun(){ 5 System.out.println("HelloWorld"); 6 } 7 } 8 new Inner().fun(); 9 } 10 public static void main(String args[]){ 11 new Test2().show(); 12 } 13 }