内部类Inner Class
将相关的类组织在一起,从而降低了命名空间的混乱。
一个内部类可以定义在另一个类里,可以定义在函数里,甚至可以作为一个表达式的一部分。
Java中的内部类共分为四种:
静态内部类static inner class (also called nested class)
成员内部类member inner class
局部内部类local inner class
匿名内部类anonymous inner class
静态内部类Static Inner Class
最简单的内部类形式。
类定义时加上static关键字。
不能和外部类有相同的名字。
被编译成一个完全独立的.class文件,名称为OuterClass$InnerClass.class的形式。
只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。
生成静态内部类对象的方式为:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
静态内部类使用代码:
1 packagecom.learnjava.innerclass;2
3 classStaticInner4 {5 private static int a = 4;6
7 //静态内部类
8 public static classInner9 {10 public voidtest()11 {12 //静态内部类可以访问外部类的静态成员13 //并且它只能访问静态的
14 System.out.println(a);15 }16
17 }18 }19
20 public classStaticInnerClassTest21 {22
23 public static voidmain(String[] args)24 {25 StaticInner.Inner inner = newStaticInner.Inner();26 inner.test();27 }28 }
成员内部类Member Inner Class
成员内部类也是定义在另一个类中,但是定义时不用static修饰。
成员内部类和静态内部类可以类比为非静态的成员变量和静态的成员变量。
成员内部类就像一个实例变量。
它可以访问它的外部类的所有成员变量和方法,不管是静态的还是非静态的都可以。
在外部类里面创建成员内部类的实例:
this.new Innerclass();
在外部类之外创建内部类的实例:
(new Outerclass()).new Innerclass();
在内部类里访问外部类的成员:
Outerclass.this.member
详情见代码例子:
1 packagecom.learnjava.innerclass;2
3 classMemberInner4 {5 private int d = 1;6 private int a = 2;7
8 //定义一个成员内部类
9 public classInner210 {11 private int a = 8;12
13 public voiddoSomething()14 {15 //直接访问外部类对象
16 System.out.println(d);17 System.out.println(a);//直接访问a,则访问的是内部类里的a18
19 //如何访问到外部类里的a呢?
20 System.out.println(MemberInner.this.a);21 }22
23 }24
25 }26
27 public classMemberInnerClassTest28 {29
30 public static voidmain(String[] args)31 {32
33 //创建成员内部类的对象34 //需要先创建外部类的实例
35 MemberInner.Inner2 inner = new MemberInner().newInner2();36
37 inner.doSomething();38 }39 }
局部内部类Local Inner Class
局部内部类定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。
像局部变量一样,不能被public, protected, private和static修饰。
只能访问方法中定义的final类型的局部变量。
局部内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成局部内部类的实例并且调用其方法。
1 packagecom.learnjava.innerclass;2
3 classLocalInner4 {5 int a = 1;6
7 public voiddoSomething()8 {9 int b = 2;10 final int c = 3;11 //定义一个局部内部类
12 classInner313 {14 public voidtest()15 {16 System.out.println("Hello World");17 System.out.println(a);18
19 //不可以访问非final的局部变量20 //error: Cannot refer to a non-final variable b inside an inner21 //class defined in a different method22 //System.out.println(b);23
24 //可以访问final变量
25 System.out.println(c);26 }27 }28
29 //创建局部内部类的实例并调用方法
30 newInner3().test();31 }32 }33
34 public classLocalInnerClassTest35 {36 public static voidmain(String[] args)37 {38 //创建外部类对象
39 LocalInner inner = newLocalInner();40 //调用外部类的方法
41 inner.doSomething();42 }43
44 }
匿名内部类Anonymous Inner Class
匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。
匿名内部类隐式地继承了一个父类或者实现了一个接口。
匿名内部类使用得比较多,通常是作为一个方法参数。
1 packagecom.learnjava.innerclass;2
3 importjava.util.Date;4
5 public classAnonymouseInnerClass6 {7
8 @SuppressWarnings("deprecation")9 publicString getDate(Date date)10 {11 returndate.toLocaleString();12
13 }14
15 public static voidmain(String[] args)16 {17 AnonymouseInnerClass test = newAnonymouseInnerClass();18
19 //打印日期:
20 String str = test.getDate(newDate());21 System.out.println(str);22 System.out.println("----------------");23
24 //使用匿名内部类
25 String str2 = test.getDate(newDate()26 {27 });//使用了花括号,但是不填入内容,执行结果和上面的完全一致28 //生成了一个继承了Date类的子类的对象
29 System.out.println(str2);30 System.out.println("----------------");31
32 //使用匿名内部类,并且重写父类中的方法
33 String str3 = test.getDate(newDate()34 {35
36 //重写父类中的方法
37 @Override38 @Deprecated39 publicString toLocaleString()40 {41 return "Hello: " + super.toLocaleString();42 }43
44 });45
46 System.out.println(str3);47 }48 }
生成的.class文件中,匿名类会生成OuterClass$1.class文件,数字根据是第几个匿名类而类推。
Swing中使用内部类的例子如下:
1 packagecom.learnjava.innerclass;2
3 importjava.awt.event.ActionEvent;4 importjava.awt.event.ActionListener;5 importjava.awt.event.WindowAdapter;6 importjava.awt.event.WindowEvent;7
8 importjavax.swing.JButton;9 importjavax.swing.JFrame;10
11 public classSwingTest12 {13 public static voidmain(String[] args)14 {15 JFrame frame = new JFrame("JFrame");16 JButton button = new JButton("JButton");17
18 button.addActionListener(newActionListener()19 {20 //new出来一个实现了ActionListener接口的类的实例
21
22 @Override23 public voidactionPerformed(ActionEvent arg0)24 {25 System.out.println("Hello World");26
27 }28 });29
30 //加入按钮
31 frame.getContentPane().add(button);32
33 //设置关闭行为
34 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);35
36 frame.setSize(200, 200);37
38 frame.addWindowListener(newWindowAdapter()39 {40 //也可以使用继承了适配器类的匿名内部类
41 @Override42 public voidwindowClosing(WindowEvent e)43 {44
45 System.out.println("Closing");46 System.exit(0);47 }48 });49 frame.setVisible(true);50 }51
52 }