```java
class Outer{
class Inner{
//内部类
}
}
```
上述定义的`Outer`是一个普通类,而`Inner`是一个Inner Class,它与普通类有个最大的不同,就是Inner Class的实例不能单独存在,必须依附于一个Outer Class的实例。
```java
public class Main{
public static void main(String[] args){
Outer outer = new Outer("hahaha");
Outer.Inter inner = outer.new Inner();
inner.hello();
}
}
class Outer{
private String name;
Outer(String name){
this.name = name;
}
class Inner{
void hello(){
SYstem.out.println("Hello, "+Outer.this.name);
}
}
}
```
要实例化一个`Inner`,我们必须首先创建一个`Outer`的实例,然后,调用`Outer`实例的`new`来创建`Inner`实例。
# 匿名类
还有一种定义Inner Class的方法,它不需要在Outer Class中明确地定义这个Class,而是在方法内部,通过匿名类(Anonymous Class)来定义。
```java
public class Main{
public static void main(String[] args){
Outer outer = new Outer("hahaha");
outer.asyncHello();
}
}
class Outer{
private String name;
Outer(String name){
this.name = name;
}
void asyncHello(){
Runnable r = new Runnable(){
@Override
public void run(){
System.out.println("Hello, "+Outer.this.name);
}
};
new Thread(r).start();
}
}
```
观察`asyncHello()`方法,我们在方法内部实例化了一个`Runnable`。`Runnable`本身是接口,接口是不能实例化的,所以这里实际上是定义了一个实现了`Runnable`接口的匿名类,并且通过`new`实例化该匿名类,然后转型为`Runnable`。在定义匿名类的时候就必须实例化它,定义匿名类的写法如下
```java
Runnable r = new Runnable(){
//实现必要的抽象方法...
}
```
匿名类和Inner Class一样,可以访问Outer Class的`private`字段和方法。之所以我们要定义匿名类,是因为在这里我们通常不关心类名,比直接定义Inner Class可以少写很多代码。
观察Java编译器编译后的`.class`文件可以发现,`Outer`类被编译为`Outer.class`,而匿名类被编译为`Outer$1.class`。如果有多个匿名类,Java编译器会将每个匿名类依次命名为`Outer$1`、`Outer$2`、`Outer$3`。除了接口外,匿名类也完全可以继承自普通类。
# 静态内部类
最后一种内部类和Inner Class类似,但是使用`static`修饰,称为静态内部类(Static Nested Class)。
```java
public class Main{
public static void main(String[] args){
Outer.StaticNested sn = new Outer.StaticNested();
sn.hello();
}
}
class Outer{
private static String NAME = "OUTER";
private String name;
Outer(String name){
this.name = name;
}
static class StaticNested{
void hello(){
System.out.println("Hello, "+Outer.NAME);
}
}
}
```
用`static`修饰的内部类和Inner Class有很大的不同,它不再依附于`Outer`的实例,而是一个完全独立的类,因此无法引用`Outer.this`,但它可以访问`Outer`的`private`静态字段和静态方法。如果把`StaticNested`移到`Outer`之外,就失去了访问`private`的权限。Static Nested Class是独立类,但拥有Outer Class的`private`访问权限。