将一个类的定义放到另一个类定义中,这个类就叫’内部类‘。内部类不是’合成‘,不是在类中声明一个指向别的对象的句柄。
class Outer {
class Inner {
void innerFun() {
System.out.println("Inner");
}
}
void outerFun() {
System.out.println("Outer");
Inner inner = new Inner();
inner.innerFun();
}
Inner getInner() {
return new Inner();
}
public static void main(String args) {
//Inner inner = new Inner(); //You cannot create an inner object like this
//Outer.Inner inner = new Outer.Inner(); //nor like this
Outer outer = new Outer();
//Outer.Inner inner = new outer.Inner(); //Nor like this
Outer.Inner inner = outer.getInner(); //We can ceate an inner object like this
}
}
1. 内部类和上溯造型(Upcasting)
我们可以通过内部类将接口(或者抽象类)的具体实现隐藏起来,只通过外部类方法返回实现了接口的内部类对象,调用者只能通过外部类获取类实例,而且此实例被以接口的句柄返回(内部类上溯到接口),调用者完全不知道类的实现细节和内部类的类型,只能通过接口调用内部类中实现的方法。外部类只能是public或者friendly的,而内部类还可以是private和protected的。
interface Runable {
void run();
}
interface Eatable {
void eat();
}
class Animal2 {
class Dog implements Runable, Eatable {
public void eat() {
System.out.println("Dog is eating.");
}
public void run() {
System.out.println("Dog is running.");
}
}
class Cat implements Runable, Eatable {
public void eat() {
System.out.println("Cat is eating.");
}
public void run() {
System.out.println("Cat is running.");
}
}
public Dog getDog() { return new Dog(); }
public Cat getCat() { return new Cat(); }
public static void main(String args[]) {
Animal2 animal = new Animal2();
Runable runDog = animal.getDog();
Eatable eatDog = (Eatable)runDog;
Eatable eatCat = animal.getCat();
Runable runCat = (Runable)eatCat;
}
}
2. 方法里的内部类
下例中,内部类定义在方法里
interface Runable {
void run();
}
interface Eatable {
void eat();
}
class Animal3 {
public Runable runDog() {
class RunDog implements Runable {
public void eat() {
System.out.println("Dog is eating.");
}
public void run() {
System.out.println("Dog is running.");
}
}
return new RunDog();
}
}
下例中内部类在一个if语句里
class Animal4 {
private void eatingDog(boolean isDog) {
if(isDog) {
//Inner class in a field of a method
class Dog {
String name = "Dog";
}
Dog dog = new Dog();
System.out.println(dog.name);
}
}
public void dogEat(boolean isDog) {
eatingDog(isDog);
}
public static void main(String args[]) {
Animal4 animal = new Animal4();
animal.dogEat(true);
}
}
4. 匿名内部类
4.1 用于实现接口
下例用一个匿名类实现了接口Eatable,并将新类实例化上溯给Eatable句柄。注意类实现最后有一个分号,因为这个类实现其实是return表达式的一部分,Java表达式应该以分号结尾。
interface Eatable {
void eat();
}
class Animal5 {
public Eatable eatingCat() {
return new Eatable() {
public void eat() {
System.out.println("Cat is eating");
}
}; //notice there is a ';'
}
public static void main(String args[]) {
Animal5 animal = new Animal5();
animal.eatingCat();
}
}
4.2 用于扩展具有带参数构造方法的类
class BaseClass {
int i = 0;
public BaseClass(int x) { i = x; }
public int getI() { return i; }
}
class ChildClass {
public BaseClass base(int x) {
return new BaseClass(x) {
public int getI() {
return super.getI()*20;
}
};
}
public static void main(String args[]) {
ChildClass child = new ChildClass();
BaseClass base = child.base(4);
}
}
4.3 用于执行自定义字段初始化的匿名类
class BaseClass {
int i = 0;
public BaseClass(int x) { i = x; }
public int getI() { return i; }
}
class ChildClass2 {
public BaseClass base() {
return new BaseClass(5) {
String name = "Dog"; //Initiate parameter
public String getName() { return name; }
};
}
}
4.4 通过实例初始化进行构造(匿名内部类不能有构造器)
class BaseClass {
int i = 0;
public BaseClass(int x) { i = x; }
public int getI() { return i; }
}
class ChildClass3 {
public BaseClass base() {
return new BaseClass(10) {
private String name;
//instance initialization for each project
{
name = "Dog";
System.out.println(name);
}
public String getName() { return name; }
};
}
}