内部类

Java 中,可以在一个类的内部定义另外一个类,这个内部定义的类,就称为内部类

内部类是一种非常有用的特性,它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可见性

当生成一个内部类的对象时,此对象与创建它的外部类的对象之间就有了一种联系,所以它能访问其外部类对象的所有成员,而不需要任何特殊条件;此外,内部类还拥有其外部类的所有元素的访问权

如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须具体的制定这个对象的类型: OuterClassName.InnerClassName

创建内部类的对象时,需要使用外部类的对象去创建该内部类的对象

1
2
3
4
5
6
7
8
9
10
public class Outer {

class Inner{

}

public static void main(String[] args) {
Inner inner = new Outer().new Inner();
}
}

在拥有外部类的对象之前,是不能创建内部类对象的,这是因为内部类对象会暗中的链接到创建它的外部类对象上;但是如果你创建的是静态内部类,那么它就不需要对外部类对象的引用

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Outer {

static class Inner{
public void test() {
System.out.println("静态内部类创建测试!");
}
}

public static void main(String[] args) {
Inner inner = new Inner();
inner.test();
}
}

输出:

静态内部类创建测试!

如果是其他的外部类中创建 Inner 内部类的对象,则:

1
2
3
4
5
6
7
public class Test {

public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.test();
}
}

输出:

静态内部类创建测试!

内部类,隐藏实现细节

方法和作用域内的内部类-局部内部类

可以在方法里面或者任意的作用域内定义内部类

方法内的内部类常常用于回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public interface LocalInner {

String value();
}

public class Outer {

public LocalInner getLocalInner(){
class MyLocalInner implements LocalInner{

private String value = "local inner";

@Override
public String value() {
return value;
}
}
return new MyLocalInner();
}
public static void main(String[] args) {
Outer outer = new Outer();
LocalInner localInner = outer.getLocalInner();
String value = localInner.value();
System.out.println(value);
}
}

输出结果:

1
local inner

匿名内部类

比较常见的匿名内部类就是创建线程时用到的匿名内部类

1
2
3
4
5
6
7
8
9
10
11
public class Test {

public Runnable thread(){
return new Runnable(){
@Override
public void run() {

}
};
}
}

匿名内部类末尾有个分号,这个分号不是用来标记内部类结束的;实际上,它标记的是表达式的结束

如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是 final 的;否则,将出现编译错误

在匿名类中不可能有命名构造器(因为它根本没名字),但是可以通过实例初始化,达到为匿名内部类创建一个构造器的效果