概述简介
如果在类中在定义一个类,则将在类中在定义的那个类称为内部类。内部类可分为成员内部类、局部内部类以及匿名内部类。
一、成员内部类
1、成员内部类简介
a、在一个类中使用内部类,可以在内部类中直接存取其所在类的私有成员变量。
b、在内部类中可以随意使用外部类的成员方法以及成员变量,尽管这些成员被修饰为private。内部类可以访问他的外部类成员,但内部类的成员只有在内部类的范围之内是可知的,不能被外部类使用。
c、内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。
d、如果在外部类和非静态方法之外实例化内部类对象,需要使用外部类。内部类的形式指定该对象的类型。
e、在实例化内部类对象时,不能再new操作符之前使用外部类名称实例化内部类对象,而是应该使用外部类的对象来创建其内部类的对象。
成员内部类的语法如下:
public class OuterClass{
private class InnerClass{
...//相关代码
}
}
例子11.8

1 public class OuterClass { 2 innerClass in = new innerClass(); // 在外部类实例化内部类对象引用 3 4 public void ouf() { 5 in.inf(); // 在外部类方法中调用内部类方法 6 } 7 8 class innerClass { 9 innerClass() { // 内部类构造方法 10 } 11 12 public void inf() { // 内部类成员方法 13 } 14 15 int y = 0; // 定义内部类成员变量 16 } 17 18 public innerClass doit() { // 外部类方法,返回值为内部类引用 19 // y=4; //外部类不可以直接访问内部类成员变量 20 in.y = 4; 21 return new innerClass(); // 返回内部类引用 22 } 23 24 public static void main(String args[]) { 25 OuterClass out = new OuterClass(); 26 // 内部类的对象实例化操作必须在外部类或外部类中的非静态方法中实现 27 OuterClass.innerClass in = out.doit(); 28 OuterClass.innerClass in2 = out.new innerClass(); 29 } 30 }
2、内部类向上转型为借口
a、如果将一个权限修饰符为pribate的内部类向上转型为其父类对象,或者直接向上转型为一个接口,在程序中就可以完全隐藏内部类的具体事项过程。
b、可以在外部提供一个接口,在接口中声明一个方法,如果在实现该接口的内部类中实现该接口的内部类中实现该接口的方法,就可以定义多个内部类以不同的方式实现接口中的同一个方法,而在一般的类中是不能多次实现接口中通一个方法的,这种技巧经常被应用在Swing变成中,可以在一个类中作出多个不同的响应事件(Swing变成技术会在后文中详细介绍)。
c、非内部类不能被声明为private或protected访问类型。
例子11.10

1 package com.lzw; 2 3 interface OutInterface { // 定义一个接口 4 public void f(); 5 } 6 7 public class InterfaceInner { 8 public static void main(String args[]) { 9 OuterClass2 out = new OuterClass2(); // 实例化一个OuterClass2对象 10 // 调用doit()方法,返回一个OutInterface接口 11 OutInterface outinter = out.doit(); 12 outinter.f(); // 调用f()方法 13 } 14 } 15 16 class OuterClass2 { 17 // 定义一个内部类实现OutInterface接口 18 private class InnerClass implements OutInterface { 19 InnerClass(String s) { // 内部类构造方法 20 System.out.println(s); 21 } 22 23 public void f() { // 实现接口中的f()方法 24 System.out.println("访问内部类中的f()方法"); 25 } 26 } 27 28 public OutInterface doit() { // 定义一个方法,返回值类型为OutInterface接口 29 return new InnerClass("访问内部类构造方法"); 30 } 31 }
3、使用this关键字获取内部类与外部类的引用
a、如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字。
例子11.09

1 public class TheSameName { 2 private int x; 3 4 private class Inner { 5 private int x = 9; 6 public void doit(int x) { 7 x++; // 调用的是形参x 8 this.x++; // 调用内部类的变量x 9 TheSameName.this.x++; // 调用外部类的变量x 10 } 11 } 12 }
二、局部内部类
内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中军可以定义内部类
例子11.12

1 interface OutInterface2 { // 定义一个接口 2 } 3 class OuterClass3 { 4 public OutInterface2 doit(final String x) { // doit()方法参数为final类型 5 // 在doit()方法中定义一个内部类 6 class InnerClass2 implements OutInterface2 { 7 InnerClass2(String s) { 8 s = x; 9 System.out.println(s); 10 } 11 } 12 return new InnerClass2("doit"); 13 } 14 }
三、匿名内部类
a、由于匿名内部类没有名称,所以你匿名内部类使用默认构造方法来生成OutInterface2对象(见例子)。在匿名内部类定义结束后,需要加分号标识,这个分号并不是代表定义内部类结束的标识,而是代表创建OutInterface2引用表达式的标识。
b、匿名内部类编译以后,会产生以“”为名称的.class文件,序号以为1~n排列,分别代表1~n个匿名内部类。
匿名类的所有实现代码需要在大括号之间进行编写。语法如下:
return new A(){ //其中A指类名
...//内部类体
}
四、静态内部类
a、在内部类前添加修饰符static,这个内部类就变为静态内部类了。
b、一个静态内部类中可以声明static成员,但是在非静态内部类中不可以声明静态成员。静态内部类有一个最大的特点,就是不可以使用外部类的非静态成员,所以静态内部类在程序开发中比较少见。
静态内部类就有以下两个特点:
(1)、如果创建静态内部类的对象,不需要其外部类的对象。
(2)、不能从静态内部类的对象中访问非静态外部类的对象。
例子14.14

1 package com.lzw; 2 3 public class StaticInnerClass { 4 int x=100; 5 static class Inner{ 6 void doitInner(){ 7 //System.out.println("外部类"+x); 8 } 9 public static void main(String args[]){ 10 System.out.println("a"); 11 } 12 } 13 }
五、内部类的继承
a、内部类和其它普通类一样可以被继承,但是继承内部类比继承普通类复杂,需要设置专门的语法来完成。
b、如下例,在某个类继承内部类时,必须硬性给与这个类一个带参数的构造方法,并且该构造方法的参数为需要继承内部类的外部类的引用,同时在构造方法体重使用a.super()语句,这样采薇继承提供了必要的对象引用。
例子11.16

1 public class OutputInnerClass extends ClassA.ClassB{ //继承内部类ClassB 2 public OutputInnerClass(ClassA a) { 3 a.super(); 4 } 5 } 6 7 class ClassA{ 8 class ClassB{ 9 ...//相关代码 10 } 11 }