内部类,顾名思义就是在一个类中的类。内部类可以访问所在类的数据,包括私有数据,而又可以对其他类隐藏,在快速实现回调函数时可以使用匿名内部类,比较便捷。

1、以下为一个简单的内部类例子,内部类可以定义为私有以对其他类隐藏起来;可以用内部类来达到实现多继承的效果。需要注意的是,通过成员函数传入内部类的变量必须定义为final类型,以保证数据的一致性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Cat extends Walk{
//private私有类,继承Walk和Eat
private class LittleCat extends Eat {
public void doSomething() {
System.out.println("Walking....Eating....");
}
}

public static void main(String[] args) {
LittleCat lCat = new Cat().new LittleCat();//创建内部类对象方式,通过先创建所在外围类对象再创建内部类对象
lCat.doSomething();
}

public void event(final String name) {
class EatFish{
public void eat() {
//name = "Tom";//在这里修改会报错,name 必须为final类型,保证数据一致
System.out.println(name);
}
}
EatFish test = new EatFish();
test.eat();
}
}

两个父类:

1
2
public class Walk {
}
1
2
public class Eat {
}

2、匿名内部类
从名称可以知道匿名就是没有类名的类,匿名内部类用于快速调用接口或抽象类等等中的方法,不需要多写一个实现类来实现调用。

抽象类

1
2
3
public abstract class Dog {
abstract void eat();
}

接口

1
2
3
public interface Animal {
void eat();
}

测试类

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
public class AnonymousDemo {

public static void main(String[] args) {

/**
* 通过创建的一个接口或抽象类分引用,快速便捷重写需要实现的方法,不需要先写一个实现类再实例化以调用方法
*/

//实现接口方式
Animal dog = new Animal() {
@Override
public void eat() {
System.out.println("like bone.");
}
};
dog.eat();//向上转型的实例,直接调用重写的eat方法

//继承抽象类的方式
Dog littleDog = new Dog() {
@Override
void eat() {
System.out.println("I like bone.");
}
};
littleDog.eat();
}
}

此外,Java的回调函数式可以通过匿名内部类来实现,比如以下例子

(1)封装的类和提供的接口
封装给别人调用的类

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
public class Person {

private EatFood eatFood;

/**
* 普通方式,构造传递引用
*/
public Person(EatFood eatSomething){
this.eatFood = eatSomething;//构造时传入引用
}


/**
* 普通方式,成员函数传递引用
*/
public Person(){
}
public void setCallBack(EatFood eatSomething) {
this.eatFood = eatSomething;//用成员函数传入引用
}

//需要调用的方法
public void eatFood() {
eatFood.eat();
}
}

调用类需要的接口定义

1
2
3
public interface EatFood {
void eat();
}

(2)实际调用
一般做法都会写一个类实现接口

1
2
3
4
5
6
7
public class EatRice implements EatFood {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("It's time to eat rice.");
}
}

然后是实际使用的类

1
2
3
4
5
6
7
8
9
10
11
12
public class PeronEatTest {
public static void main(String[] args) {
//普通方式,构造传递引用
Person personOne = new Person(new EatRice());//EatRice实现类方式。多写一个方法传入也可
personOne.eatFood();

//普通方式,成员函数传递引用
Person personOne = new Person();
EatRice eatRice = new EatRice();
personOne.setCallBack(eatRice);
personOne.eatFood();
}

如果使用匿名内部类就便捷了许多

1
2
3
4
5
6
7
8
9
10
11
12
public class PeronEatTest {
public static void main(String[] args) {
Person personTwo = new Person(new EatFood() {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("It's time to eat rice.");
}
});
personTwo.eatFood();
}
}

3、静态内部类
创建是不需要依赖于外围类,但也不能使用任何外围类的非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
public class Cat{

private String str = "cat";
private static String str_static = "cat";

private class LittleCat{
//public static String str_test = "test";//错误,非静态内部类变量不能为静态
public static final String str_test = "test";//但加上final就可以
public void doSomething() {
str = "little cat";
System.out.println("Walking....Eating....");
}
}

static class BigCat{
public void doSomething() {
//str = "little cat";//错误,静态内部类反问外围非静态变量和方法
str_static = "big cat";
System.out.println("I am a big cat.");
}
}

public static void main(String[] args) {
LittleCat lCat = new Cat().new LittleCat();//依赖外围类
lCat.doSomething();

BigCat bigCat = new BigCat();//不依赖外围类
bigCat.doSomething();
}