Table of Contents
Java内部类
1:什么是内部类
2:内部类特点
3:内部类的分类
3.1:成员内部类
3.2:本地内部类
3.3:匿名内部类
4 内部类的规则
Java内部类
1:什么是内部类
内部类(Inner Classes)的概念是在 JDK1.1 版本中开始引入的。在 Java 中,允许在一个类(或方法、语句块)的内部定义另一个类,称为内部类,有时也称为嵌套类(NestedClasses)。
内部类和外层封装它的类之间存在逻辑上的所属关系,一般只用在定义它的类或语句块之内,实现一些没有通用意义的功能逻辑,在外部引用它时必须给出完整的名称。
内部类是一个有用的特征,因为它们允许将逻辑上同属性的类组合到一起,并在另一个类中控制一个类的可视性。
public class MyFrame extends Thread {
Button myButton;
TextArea myTextArea;
int count;
public MyFrame(String title) {
super(title);
myButton = new Button("click me");
myTextArea = new TextArea();
add(myButton, BorderLayout.CENTER);
add(myTextArea, BorderLayout.NORTH);
ButtonListener bList = new ButtonListener();
myButton.addActionListener(bList);
}
class ButtonListener implements ActionListener { // 这里定义了一个内部类
public void actionPerformed(ActionEvent e) {
count++;
myTextArea.setText("button clicked " + count + " times");
}
} // end of innerclass ButtonListener
public static void main(String args[]) {
MyFrame f = new MyFrame("Inner Class Frame");
f.setSize(300, 300);
f.setVisible(true);
}
}
2:内部类特点
- 1:嵌套类(内部类)可以体现逻辑上的从属关系。同时对于其他类可以控制内部类对外不可见等。
- 2:外部类的成员变量作用域是整个外部类,包括嵌套类。但外部类不能访问嵌套类的private 成员
- 3:逻辑上相关的类可以在一起,可以有效的实现信息隐藏。
- 4:内部类可以直接访问外部类的成员。可以用此实现多继承!
- 5:编译后,内部类也被编译为单独的类,不过名称为 outclass$inclass 的形式。
3:内部类的分类
内部类按照使用上可以分为四种情形:
- (1)类级:成员式,有 static 修饰
- (2)对象级:成员式,普通,无 static 修饰
- (3)本地内部类:局部式
- (4)匿名级:局部式
3.1:成员内部类
class MyFrame extends Thread {
private int size;
public class Inner {
public void dostuff() {
size++;
}
}
public void testTheInner() {
Inner in = new Inner();
in.dostuff();
}
}
成员式内部类如同外部类的一个普通成员。成员式内部类的基本规则
- (1)可以有各种修饰符,可以用 4 种权限、static、final、abstract 定义(这点和普通的类是不同的);
- (2)若有 static 限定,就为类级,否则为对象级。类级可以通过外部类直接访问;对象级需要先生成外部的对象后才能访问。
- (3)内外部类不能同名
- (4)非静态内部类中不能声明任何 static 成员
- (5)内部类可以互相调用,如下:
class A {
// B、C 间可以互相调用
class B {
}
class C {
}
}
3.2:本地内部类
本地类(Local class)是定义在代码块中的类。它们只在定义它们的代码块中是可见的。
本地类有几个重要特性:
- (1)仅在定义了它们的代码块中是可见的;
- (2)可以使用定义它们的代码块中的任何本地 final 变量;
- (3)本地类不可以是 static 的,里边也不能定义 static 成员。
- (4)本地类不可以用 public、private、protected 修饰,只能使用缺省的。
- (5)本地类可以是 abstract 的。
class MyFrame extends Thread {
public static final int TOTAL_NUMBER = 5;
public int id = 123;
public void t1() {
final int a = 15;
String s = "t1";
class Inner {
public void innerTest() {
System.out.println(TOTAL_NUMBER);
System.out.println(id);
System.out.println(a);
// System.out.println(s);不合法,只能访问本地方法的final变量
}
}
new Inner().innerTest();
}
public static void main(String[] args) {
System.out.println("111");
}
}
3.3:匿名内部类
匿名内部类是本地内部类的一种特殊形式,也就是没有变量名指向这个类实例,而且具体的类实现会写在这个内部类里面。把上面的例子改造一下,如下所示:
class MyFrame extends Thread {
public static final int TOTAL_NUMBER = 5;
public int id = 123;
public void t1() {
final int a = 15;
String s = "t1";
new Aclass() {
public void testA() {
System.out.println(TOTAL_NUMBER);
System.out.println(id);
System.out.println(a);
// System.out.println(s);不合法,只能访问本地方法的final变量
}
}.testA();
}
public static void main(String[] args) {
Test t = new Test();
t.t1();
}
}
注意:匿名内部类是在一个语句里面,所以后面需要加“;”。匿名类的规则:
- (1)匿名类没有构造方法;
- (2)匿名类不能定义静态的成员;
- (3)匿名类不能用 4 种权限、static、final、abstract 修饰;
- (4)只可以创建一个匿名类实例
4 内部类的规则
总结一下,内部类有如下特点:
- (1)类名称只能用在定义过的范围中,除非用在限定的名称中。内部类的名称必须与所嵌套的类不同。
- (2)内部类可以被定义在方法中。这条规则较简单,它支配到所嵌套类方法的变量的访问。任何变量,不论是本地变量还是正式参数,如果变量被标记为 final,那么,就可以被内部类中的方法访问。
- (3)内部类可以使用所嵌套类的类变量和实例变量以及所嵌套的块中的本地变量。
- (4)内部类可以被定义为 abstract。
- (5)只有内部类可以被声明为 private 或 protected,以便防护它们不受来自外部类的访问。访问保护不阻止内部类使用其它类的任何成员,只要一个类嵌套另一个。
- (6)一个内部类可以作为一个接口,由另一个内部类实现。
- (7)被自动地声明为 static 的内部类成为顶层类。这些内部类失去了在本地范围和其它内部类中使用数据或变量的能力。
- (8)内部类不能声明任何 static 成员;只有顶层类可以声明 static 成员。因此,一个需求 static 成员的内部类必须使用来自顶层类的成员。