内部类

结构

1
2
3
4
5
6
7
8
class OutClass {
//属性,方法声明

//内部类
class InnerClass {
//属性,方法声明
}
}

从上可知,内部类的实现很简单,就是将类的定义放在另一个类中,即:place a class definition within another class definition

使用 .this.new

  • .this 使用

    当在内部类中要使用外部类的引用,需要使用.this,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {
public void play() {
System.out.println("Test play");
}

//inner class
private class Selector {
public Test getTest() {
//返回一个外部类的引用。也可以:return new Test();
return Test.this;
}
}

public static void main(String[] args) {
Test.Selector selector1 = test.selector();
selector1.getTest().play();
}
}
//output
Test play
  • .new 使用

    当在其他外部类中需要内部类的引用时,需要使用.new,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {
//inner class
private class Selector {
public void play() {
System.out.println("Test playdd");
}
}
public static void main(String[] args) {
Test test1 = new Test(10);
/** 在返回内部类引用时,使用 outClass.new
*
* 但是如果为静态内部类时,则不需要使用.new
* Test.Selector selector3 = new Test.Selector();
*/
Test.Selector selector2 = test1.new Selector();
selector2.play();
}
}
//output
Test playdd

内部类注意事项

  • 必须由外部类对象创建内部类,除非是静态内部类(即嵌套类)。

    It’s not possible to create an object of the inner class unless you already have an object of the outer class

  • 内部类不能声明静态方法。

  • 内部类可以访问外部类的所有元素。

    The inner class secretly captures a reference to the particular object of the enclosing class that was responsible for creating it

可以通过分析以下代码得知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test {
private String[] iterms;
private int next = 0;
public Test(int size) {
iterms = new String[size];
}
public void add(String iterm) {
if (next < iterms.length)
iterms[next++] = iterm;
}
//inner class
private class Selector {
private int i = 0;
public boolean end() {
return i == iterms.length;
}
}
}

编译后的class文件

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
27
28
29
public class Test
{
private String[] iterms;
private int next = 0;

public Test(int size) {
this.iterms = new String[size];
}

public void add(String iterm) {
if (this.next < this.iterms.length) {
this.iterms[(this.next++)] = iterm;
}
}

private class Selector {
private int i = 0;

private Selector() {}

public boolean end() {
/**可知,当内部类在访问外部类的元素时,内部类会拥有一个
* 负责创建外部类的特殊对象(上述英文翻译很拗口,
* 意会即可O(∩_∩)O哈哈~)
*/
return this.i == Test.this.iterms.length;
}
}
}

继承内部类

  • 继承

    因为内部类构造器必须持有一个外部类的引用,因此继承内部类时比较麻烦(简直是反人类啊!!!)。问题的根源是:内部类持有的外部类引用必须初始化。

1
2
3
4
5
6
7
8
9
package com.houlong.java.innnerclass;
class WithInner {
//内部类
class Inner {
public void deplay() {
System.out.println("hah");
}
}
}

继承上述内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.houlong.java.innnerclass;
public class InheritInner extends WithInner.Inner {
public InheritInner(WithInner withInner) {
withInner.super();
}

public static void main(String[] args) {
WithInner withInner = new WithInner();
InheritInner inheritInner = new InheritInner(withInner);
inheritInner.deplay();
}
}
//output
hah

其中使用InheritInner类的默认构造器是不行的,会报错:

1
No enclosing instance of type 'com.houlong.java.innerclass.WithInner' is in scope

必须在构造器中加上

1
enclosingClassReference.super();
  • 当外部类被继承时,内部类不能被override
1
2
3
4
5
6
7
8
9
10
11
12
13
class WithInner {
public WithInner() {
System.out.println("WithInner");
//创建一个内部类,用于测试
new Inner();
}
//内部类
class Inner {
public Inner() {
System.out.println("WithInner.Inner");
}
}
}

继承类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class InheritInner extends WithInner {
//内部类
class Inner {
public Inner() {
System.out.println("InheritInner.Inner");
}
}
public static void main(String[] args) {
new InheritInner();
}
}


//输出:
WithInner
WithInner.Inner

可见,在父类WithInner的构造函数中调用的内部类Inner为其本身内部类,而不是子类中的。

如果想要实现override功能,代码如下:

1
2
3
4
5
6
7
8
9
10
class WithInner {
private Inner inner;
//内部类
class Inner {
public Inner() {
System.out.println("WithInner.Inner");
}
}
public void insertYolk(Inner yy) { }
}

继承类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class InheritInner extends WithInner {
public InheritInner() {
insertYolk(new Inner());
}
//内部类,并继承相关内部类
class Inner extends WithInner.Inner {
public Inner() {
System.out.println("InheritInner.Inner");
}
}
public static void main(String[] args) {
new InheritInner();
}
}

//输出:
WithInner.Inner
InheritInner.Inner
Fork me on GitHub