- 当我们创建普通类的对象时,是这样的,如下所示:
public class Person {}
public class Test {
public static void main(String[] args) {
// 创建普通类的对象
// 类名 对象名 = new 类名();
Person p = new Person();
}
}- 而内部类是什么?内部类表示的事物是外部类的一种,内部类单独出现没有任何意义,如:人的心脏或汽车的发送机。
- 试问:人的心脏,从人体内拿出来有意义吗?没有任何意义,就算移植,也需要尽快移植到人体内,让其为病人发挥作用。
- 试问:汽车的发送机,从汽车中拿出来有意义吗?没有任何意义,就算坏了,也要修好装回汽车中,才能更好的为汽车发挥作用,提供动力。
- 假设成员内部类是这样的,如下所示:
public class Outer { // 外部类
class Inner { // 内部类
String name;
int age;
}
}- 那么,在编译的时候,Java 会生成两个字节码文件,如:
Outer.class以及Outer$Inner.class,并且Outer$Inner.class也表明了内部类Inner是依托于Outer而存在的,单独出现没有意义。 - 现在,我们要在外部类中访问内部类的成员,也是需要创建内部类的对象的,如下所示:
public class Outer { // 外部类
class Inner { // 内部类
String name;
int age;
}
public void show(){
Inner inner = new Inner();
inner.name = "xxx";
inner.age = 18;
...
}
}
- 为什么需要那样写,那是因为 JVM 会在 Outer 的实例方法中注入 this 变量,如下所示:
public class Outer { // 外部类
String name;
int age;
class Inner { // 内部类
String name;
int age;
}
public void show(Outer this){
Inner inner = new Inner();
inner.name = "xxx";
inner.age = 18;
...
}
}
- 这样我们就可以在实例方法中,访问外部类
Outer的属性或行为,如下所示:
public class Outer { // 外部类
String name;
int age;
class Inner { // 内部类
String name;
int age;
}
public void show(Outer this){
this.name = "outerxxx"
this.age = 19;
Inner inner = new Inner();
inner.name = "xxx";
inner.age = 18;
...
}
}
- 当在 main 方法实例化 Outer 的对象时,如下所示:
public class Test {
public static void main(String[] args) {
// 创建普通类的对象
// 类名 对象名 = new 类名();
Outer o = new Outer ();
// JVM 会自动注入 this 变量,类型是 Outer
o.show();
}
}
但是,为什么在 show 方法却要创建 Inner 的对象?是因为在 show 方法中只有 this 变量,是 Outer 类型,而不是 Inner 类型,如下所示:
public class Outer { // 外部类
String name;
int age;
class Inner { // 内部类
String name;
int age;
}
public void show(Outer this){
// this 表示调用者的地址
// this 的类型是 Outer
this.name = "outerxxx"
this.age = 19;
// 在show 方法中没有 Inner 对象,所以当然需要创建 Inner 对象
// 类名 对象名 = new Inner()
Inner inner = new Inner();
inner.name = "xxx";
inner.age = 18;
...
}
}
- 此时,我们可以将 show 方法改造一下,如下所示:
public class Outer { // 外部类
String name;
int age;
class Inner { // 内部类
String name;
int age;
}
public Inner getInstance(Outer this){
// this 表示调用者的地址
// this 的类型是 Outer
this.name = "outerxxx"
this.age = 19;
Inner inner = new Inner();
inner.name = "xxx";
inner.age = 18;
return inner;
}
}
- 那么,在 main 方法中就是这么调用,如下所示:
public class Test {
public static void main(String[] args) {
// 创建普通类的对象
// 类名 对象名 = new 类名();
Outer o = new Outer();
// Outer.Inner 表示内部类不能脱离外部类而存在,内部类依托于外部类,正如:心脏不能脱离人
// Outer.Inner 表示 Inner 是 Outer 的子类
Outer.Inner i = o.getInstance()
}
}
- 当然,你也可以这么写,如下所示:
public class Test {
public static void main(String[] args) {
// 创建普通类的对象
// 类名 对象名 = new 类名();
Outer o = new Outer();
// Outer.Inner 表示内部类不能脱离外部类而存在,内部类依托于外部类,正如:心脏不能脱离人
// Outer.Inner 表示 Inner 是 Outer 的子类
Outer.Inner i = o.new Inner();
}
}
- 如何理解?
public class Test {
public static void main(String[] args) {
// 表示先创建外部类的对象
Outer o = new Outer();
}
}public class Test {
public static void main(String[] args) {
// 表示先创建外部类的对象
Outer o = new Outer();
// 在外部类的对象基础上在创建内部类对象
o.new Inner();
}
}和 下面的代码,作用是一样的:
public class Outer { // 外部类
String name;
int age;
class Inner { // 内部类
String name;
int age;
}
public Inner getInstance(Outer this){
// this 表示调用者的地址
// this 的类型是 Outer
this.name = "outerxxx"
this.age = 19;
Inner inner = new Inner();
inner.name = "xxx";
inner.age = 18;
return inner;
}
}
public class Test {
public static void main(String[] args) {
// 创建普通类的对象
// 类名 对象名 = new 类名();
Outer o = new Outer();
// Outer.Inner 表示内部类不能脱离外部类而存在,内部类依托于外部类,正如:心脏不能脱离人
// Outer.Inner 表示 Inner 是 Outer 的子类
Outer.Inner i = o.getInstance()
}
}
public class Test {
public static void main(String[] args) {
// 创建普通类的对象
// 类名 对象名 = new 类名();
Outer o = new Outer();
// 获取的是外部类的方法,在外部类方法的内部创建了内部类的对象
Outer.Inner i = o.getInstance()
}
}
public class Test {
public static void main(String[] args) {
// 只是获取的是外部类的对象
Outer o = new Outer();
// 如果想要继续创建内部类对象
// 类名 对象名 = new 类名();
Outer.inner i = o.new Inner();
}
}
那么,就可以继续推导了,如下所示:
Outer o = new Outer();
Outer.inner i = o.new Inner();
Outer.inner i = new Outer().new Inner();