一、内部类(Inner Class)

注:有些地方把内部类叫做Nested Class,这一般是C++的叫法;在Java中常见的是称之为 Inner Class

1.什么是内部类?

内部类:即定义在类中的类,可以理解为是外部类的一个成员,不过这个成员是一个类。

2.为什么有内部类?

内部类可以访问并修改外部类的private修饰的成员变量,更加方便访问;并且其一些特殊情况如匿名内部类更简洁。

3.如何使用内部类?

较为常规的如下:

class Outer {
class Inner {
// 定义了一个Inner Class
}
}

其中相对而言,Outer属于外部类,Inner属于Outer的内部类,具体使用如下:

public class Main {
public static void main(String[] args) {
Outer outer = new Outer("Nested"); // 实例化一个Outer
Outer.Inner inner = outer.new Inner(); // 实例化一个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的实例。因为:

Inner Class除了有一个this指向它自己,还隐含地持有一个Outer Class实例,可以用Outer.this访问这个实例。所以,实例化一个Inner Class不能脱离Outer实例。

在编译后,会额外产生 “外部类名$内部类名.class”文件

重识Java第七天打卡----面向对象进阶3【内部类、静态内部类、匿名内部类】_jvm

4.注意事项

  • 内部类不能与包含它的外部类名相同。
  • 内部类不光可以在类中定义,也可以在程序块之中定义。(比如在方法中定义内部类,但是只能访问方法中final修饰的局部变量)
  • 静态内部类和匿名内部类均属于内部类的特殊情况

二、静态内部类(Static Nested Class)

1.什么是静态内部类?

简言之,就是用static修饰的内部类。但此时该类其实实质上已经与外部类处于平行关系了,但还有一些特殊的作用。

2.为什么有静态内部类?

  1. 静态内部类可以限制内部类的权限,其只能访问外部类的成员,但是没有权限修改,这样安全性得以提高
  2. 静态内部类还是可以访问外部类成员的,有些情况需要使用。

3.如何使用静态内部类?

具体代码:

public class Test3 {
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);
// Outer.this.name = "windx"; //会报错
}
}
}
}

编译后结果:

重识Java第七天打卡----面向对象进阶3【内部类、静态内部类、匿名内部类】_java_02

4.注意事项

它不再依附于Outer的实例,可以算是一个完全独立的类,因此无法引用Outer.this

三、匿名内部类(Anonymous Class)

1.什么是匿名内部类?

字面意思是没有名字的内部类。常常在外部类的方法中使用匿名内部类或者作为抽象类的延伸使用匿名内部类

2.为什么有匿名内部类?

为了少写代码,提高编译效率

3.如何使用匿名内部类?

具体代码:

abstract class Person {
public abstract void Sleep();
}
public class Test {
public static void main(String[] args){
Person person = new Person(){
public void Sleep(){
System.out.println("睡觉");
}
};
person.Sleep();
}
}

以上是两个类,一个Person抽象类,一个具体的Test类,两者必须结合起来使用。
此处,匿名类的作用就体现在可以少写一个实现Person抽象类的具体类,而是直接使用Person类名,并在创建实例的时候带上具体的方法。后面也可以正常使用。