一、成员内部类
1.最常规的内部类。在其中可以访问任何权限的外部类方法。
1 public class Outer{//外部类 2 3 private int a = 10; 4 public class Inner//成员内部类 5 { 6 int b = 12; 7 public void speak() 8 { 9 System.out.println("访问外部类中A="+a);//访问私有属性a 10 System.out.println("访问内部类中B="+b); 11 } 12 } 13 public static void main(String[] args) 14 { 15 Outer o = new Outer(); 16 Inner i = o.new Inner(); 17 i.speak(); 18 } 19 }
2.外部类对象与成员内部类对象的关系。
public static void main(String[] args) { Outer o = new Outer();//创建一个外部类对象,对象引用名为o Inner i = o.new Inner();//使用外部类对象创建内部类对象,对象引用名为i i.speak(); }
上述例子中的main方法中,分别创建了内部和外部类的对象,其中内部类对象还可以像下面用外部类的匿名对象创建:
Outer.Inner oi = new Outer().new Inner();
3.在成员内部类中,访问外部类的属性和方法。
1 public class Outer{//外部类 2 3 private int a = 10; 4 public void talk() 5 { 6 a++; 7 } 8 public class Inner//成员内部类 9 { 10 int b = 12; 11 public void speak() 12 { 13 System.out.println("访问外部类中A="+a); 14 System.out.println("访问内部类中B="+b); 15 Outer.this.a=21;//类名调用 16 talk();//直接调用 17 System.out.println("访问外部类中A="+a); 18 } 19 } 20 public static void main(String[] args) 21 { 22 Outer.Inner oi = new Outer().new Inner(); 23 oi.speak(); 24 } 25 }
4.编译后,会产生两个class文件,分别为Outer.class和Outer$Inner.class,后者便是成员内部类的完整类名。
5.外部类无法直接使用内部类的属性和方法,需要通过创建内部类的对象来访问。
//外部类的talk()方法
public void talk() { a++; //speak();//错误的 Inner in = new Inner();
in.speak();//正确的
}
6.对于同名的属性或方法,借助this关键字,可以恰当区分外部类属性(方法)和内部类属性(方法)。
二、静态内部类
1.静态内部类与静态方法类似,只能访问外部类的static成员,需要通过对象引用才能访问外部类的实例变量和实例方法。
2.对于同名的属性或方法,使用“类名.静态成员”访问外部类的成员。
1 public class Outer{//外部类 2 3 private int a = 10; 4 static int b = 12; 5 static public class Inner//静态内部类 6 { 7 int b = 21; 8 public void speak() 9 { 10 System.out.println("访问外部类中A="+new Outer().a);//访问外部类非静态成员 11 System.out.println("访问内部类中B="+b);//访问内部类静态成员 12 System.out.println("访问外部类中B="+Outer.b);//访问外部类静态成员 13 } 14 } 15 public static void main(String[] args) 16 { 17 Inner i = new Inner(); 18 i.speak(); 19 } 20 }
3.用完整类名可直接创建对象,不需要外部类的对象辅助了。
Inner i = new Inner();
三、方法(局部)内部类
1.顾名思义,将内部类定义在外部类的方法中就是方法内部类,其只在该方法的内部可见。(方法体、语句块中均可以定义内部类)
1 public class Outer{//外部类 2 3 int a = 10; 4 int b = 12; 5 //方法体开始 6 public void print() 7 { 8 class Inner//方法内部类 9 { 10 int b = 21; 11 public void speak() 12 { 13 System.out.println("访问外部类中A="+a); 14 System.out.println("访问内部类中B="+b); 15 System.out.println("访问外部类中B="+Outer.this.b); 16 } 17 } 18 Inner i = new Inner();//创建内部类对象 19 i.speak();//调用内部类方法 20 } 21 //方法体结束 22 public static void main(String[] args) 23 { 24 Outer o = new Outer();//创建外部类对象 25 o.print();//调用外部类方法 26 } 27 }
2.方法内部类不能使用访问控制符和static修饰符。
3.方法内部类可以访问外部类的成员,但对于方法中的参数和局部变量,必须有final修饰符(即变为常量)才可以访问。
1 public void print() 2 { 3 int c; 4 class Inner//方法内部类 5 { 6 public void speak() 7 { 8 System.out.println("访问外部类中A="+a); 9 System.out.println("访问内部类中B="+c);//出现错误 10 System.out.println("访问外部类中B="+Outer.this.b); 11 } 12 } 13 Inner i = new Inner();//创建内部类对象 14 i.speak();//调用内部类方法 15 }
出现过错误的地方一定要牢牢记住!!!
四、匿名内部类
1.将类的定义和创建实例放在一起进行,只能使用一次的,这种没有名字的类叫匿名内部类。
2.匿名内部类可以继承一个类或实现一个接口,但不能同时。
1 import java.awt.event.WindowAdapter; 2 import java.awt.event.WindowEvent; 3 import javax.swing.JFrame; 4 5 public class WinEvent{ 6 7 public static void main(String[] args) { 8 //MyListener t = new MyListener(); 9 JFrame frame = new JFrame(); 10 frame.addWindowListener( 11 new WindowAdapter()//匿名内部类只能使用一次 12 { 13 public void windowClosing(WindowEvent e) 14 { 15 System.out.println("123"); 16 } 17 } 18 ); 19 frame.setSize(400, 500); 20 frame.setLocation(200, 200); 21 frame.setVisible(true); 22 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 23 } 24 }
3.匿名内部类的一个重要应用是编写GUI的事件处理程序,如上例。
最后,我们为什么要使用内部类呢?
1.内部类提供更好的封装。
2.内部类的方法可以直接访问外部类的所有数据,包括私有数据。
3.内部类可以更方便的实现功能,比如匿名内部类。