一、常规内部类
所谓常规内部类,或者说内部类,指的就是除去后面三种之外的内部类(这算什么解释。。。)先写一个最简单的内部类的例子:
/* * 常规内部类demo。 */ package com.wang.java.Demo; public class Outer{ private int x = 1; public Outer(){ System.out.println("Outer sign"); } class Inner{ public Inner(){ System.out.println("Inner Sign!"); } private int x =2; public void add(){ int x = 3; System.out.println(x); System.out.println(this.x); System.out.println(Outer.this.x); } } public static void main(String[] args) { Inner inner = new Outer().new Inner(); inner.add(); } }
编译后的运行结果:outer sign
Inner Sign
3
2
1
在上面的例子里可以清晰的看到:
1 内部类就像一个实例成员一样存在于外部类中。
2 内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。
3 内部类中的this 指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名 .this 的方式 获得。
4 内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。
内部类的创建方法:
1 在外部类的内部,可以用 Inner inner = new Inner(); 方法直接创建
2 在外部类外部,必须先创建外部类实例,然后再创建内部类实例,除了上面 Inner inner = new Outer().new Inner() 的写法以外,还有 Outer outer = new Outer(); Inner inner = outer.new Inner(); 的写法
二、 局部内部类:
把类定义在方法体内, 这个类称之为局部内部类。
/* * 局部内部类Demo */ package com.wang.java.Demo; public class Outer01 { private int x = 1; public void doSomeThing() { final int y = 2; class Inner { int x = 3; void print() { int x = 4; System.out.print(x); System.out.print(this.x); System.out.println(Outer01.this.x); System.out.print(y); } } Inner inner = new Inner(); inner.print(); } public static void main(String[] args) { Outer01 o = new Outer01(); o.doSomeThing(); } }
运行结果:4 、 3 、 1 、 2
1 局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public 、 private 、 protected 、 static 、 transient 等
2 局部内部类只能在声明的方法内是可见的,因此定义局部内部类之后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,一定是要先声明后使用,否则编译器会说找不到。
3 局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。
三、匿名内部类:
把内部类的定义和声明写到一起时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,因此我们叫它匿名内部类。
/* * 匿名内部类demo */ package com.wang.java.Demo; public class Wife { public interface Dear{ public void byfriendlly(); public void angry(); } public static void main(String[] args) { Dear wife = new Dear(){ @Override public void byfriendlly() { System.out.println("亲亲 ^_^"); } @Override public void angry() { System.out.println("别给我说话,离我远点!"); } }; wife.byfriendlly(); System.out.println("++++++++++++++++++++"); wife.angry(); } }
1 第一匿名内部类可以是个接口,这个没什么好奇怪的哈。
2 第12 行到第 21 行是一个语句,就是定义了一个对象,因此 21 行大括号后面有个分号。
3 匿名内部类用 new Dear (){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。
4 匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。
方法参数内的匿名内部类 :
/* * 方法参数内的局部内部类Demo */ package com.wang.java.Demo; public class Dog { static abstract class Ball{ abstract String getName(); } void play(Ball ball){ System.out.println(ball.getName()); } public static void main(String[] args) { Dog dog = new Dog(); dog.play(new Ball(){ @Override String getName() { return "pi qiu"; } }); }
四、 静态嵌套类
当一个内部类前面用static 修饰时,我们称之为静态嵌套类或者说静态内部类。
package com.wang.java.Demo; public class Outer02 { static int x = 1; static class Inner{ void print(){ System.out.println("Inner++"+x); } } public static void main(String[] args) { Outer02.Inner inner = new Outer02.Inner(); inner.print(); } }
因为静态嵌套类和其他静态方法一样只能访问其它静态的成员,而不能访问实例成员。因此静态嵌套类和外部类(封装类)之间的联系就很少了,他们之间可能也就 是命名空间上的一些关联。上面例子中你需要注意的就是静态嵌套类的声明方法 new Outer.Nest() 连续写了两个类名,以至于我们都怀疑前面的 Outer 是个包名了,好在包名一般都小写的,要不还真分不清 ……