Java内部类

使用内部类原因:

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
  • 内部类可以对同一个包中的其他类隐藏起来。
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。

使用内部类访问对象状态

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
30
31
32
33
34
35
36
37
package com.example.demo.test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

public class InnerClassTest {
public static void main(String[] args) {
Person person = new Person(true);
person.run();
}
}

class Person {

private boolean isHungry;

public Person(boolean isHungry) {
this.isHungry = isHungry;
}

public void run() {
Eat eat = new Eat();
eat.eatSomthing();
}

public class Eat {

public void eatSomthing() {
if (isHungry) {
System.out.println("Eating!");
}
}
}
}

运行结果:

1
Eating!

在内部类Eat中,可以访问到类外部的isHungary变量。

内部类对象拥有一个对外围类对象的引用,如下图:

这个引用outer类似于super,但是outer并不是Java的关键字。

Eat内部类中,没有定义构造器,编译器为其生成了一个默认的构造器,代码如下:

1
2
3
public Eat(Person person) {
outer = person;
}

Person类中run方法new一个Eat对象时,默认传入一个this引用参数,代码如下:

1
Eat eat = nwe Eat(this);

内部类的特殊语法规则

表达式OuterClass.this表示外围类的引用。例如,在Eat内部类中:

1
2
3
if (Person.this.isHungry) {
System.out.println("Eating!");
}

表达式outerObject.new InnerClass(construction parameters)表示内部对象的构造器。例如,在Person类的run方法中:

1
Eat eat = this.new Eat();

当使用另一个外部对象new一个内部对象时,这种写法就比较有意义。

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
30
31
32
33
34
35
36
37
38
package com.example.demo.test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

public class InnerClassTest {
public static void main(String[] args) {
Person person = new Person(false);
person.run();
}
}

class Person {

private boolean isHungry;

public Person(boolean isHungry) {
this.isHungry = isHungry;
}

public void run() {
Person person = new Person(true);
Eat eat = person.new Eat();
eat.eatSomthing();
}

public class Eat {

public void eatSomthing() {
if (Person.this.isHungry) {
System.out.println("Eating!");
}
}
}
}

运行结果:

1
Eating!

创建了一个isHungary为false的person对象,如果创建这个对象的内部对象,程序运行不会打印出任何结果。在run方法中,创建的isHungary为true的person的内部对象,所以程序运行有输出结果。

表达式OuterClass.InnerClass表示在外围类中引用内部类。也可以在Person类外部实现run方法的逻辑:

1
2
3
4
5
6
7
public class InnerClassTest {
public static void main(String[] args) {
Person person = new Person(true);
Person.Eat eat = person.new Eat();
eat.eatSomthing();
}
}

运行结果:

1
Eating!

局部内部类

Eat类只有在run方法中使用过一次,像这种只使用一次的内部类,可以在方法中定义一个局部内部类。

1
2
3
4
5
6
7
8
9
10
11
12
public void run() {
class Eat {
public void eatSomthing() {
if (isHungry) {
System.out.println("Eating!");
}
}
}

Eat eat = new Eat();
eat.eatSomthing();
}

局部内部类的作用域声明这个局部类的块中,不能用public或private访问修饰符进行声明。

匿名内部类

如果只想要创建一个对象,并不关系这个类是什么,可以使用匿名内部类。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.example.demo.test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

public class InnerClassTest {
public static void main(String[] args) {
Person person = new Person(true);
person.run();
}
}

class Person {

private boolean isHungry;

public Person(boolean isHungry) {
this.isHungry = isHungry;
}

public void run() {
Man man = new Man() {
@Override
public void eat() {
if (isHungry) {
System.out.println("Eating!");
}
}
};

man.eat();
}


}

interface Man {
void eat();
}

运行结果:

1
Eating!

静态内部类

当不需要内部类引用外部类对象时,可以将内部类声明为static,即静态内部类。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.example.demo.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class InnerClassTest {
public static void main(String[] args) {
Person.Number number = Person.run(new ArrayList<Integer>() {{
add(1);
add(2);
add(3);
}
});

System.out.println(number);
}
}

class Person {

public static Number run(List<Integer> integerList) {
return new Number(Collections.min(integerList), Collections.max(integerList));
}

public static class Number {
private Integer min;
private Integer max;

public Integer getMin() {
return min;
}

public void setMin(Integer min) {
this.min = min;
}

public Integer getMax() {
return max;
}

public void setMax(Integer max) {
this.max = max;
}

public Number(Integer min, Integer max) {
this.min = min;
this.max = max;
}

@Override
public String toString() {
return "Number{" +
"min=" + min +
", max=" + max +
'}';
}
}
}

运行结果:

1
Number{min=1, max=3}
-------------本文结束感谢您的阅读-------------

本文标题:Java内部类

文章作者:huihui

发布时间:2018年10月08日 - 17:10

最后更新:2019年02月14日 - 19:02

原始链接:http://101.200.47.120:8011/2018/10/08/Java内部类/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。