Java的内部类
Java设计内部类的意义:
(1)、我们知道java是单继承的,为了能够实现多继承,java引入了接口,但是仅有的接口在使用上还是无法完全实现多继承。使用内部类的最主要的原因是-------->每个内部类都能独立的继承自一个接口的实现,所以无论外围类是否已经继承了某个接口的实现,对内部类都没有影响。如果没有内部类提供的可以继承多个具体的或者抽象类的能力,一些设计与编程问题就很难解决。
(2)、内部类可以有多个实例,每个实例都有自己的状态和信息,并且与外围类对象的信息相互独立。
(3)、内部类并没有令人迷惑的“is-a”关系,它就是一个独立的实体。
(4)、内部类看起来像是一种代码隐藏机制,将类置于类的内部,它了解外部类,并能与之通信,某些情况下使用内部类可以使得代码看起来更加优雅清晰。
我们来看写代码,来论证下java为何要设计内部类:
定义了两个接口,我们用两种方式来实现一下这两个接口,一种是正常的实现,一种是采用内部类的形式来实现,
具体看如下代码
//接口一
public interface ClickA {
void souTime();
}
//接口二
public interface ClickB {
void say();
}
//第一种实现类
public class TestX implements ClickA,ClickB {
@Override
public void souTime() {
System.out.println("来自X类的输出 souTime");
}
@Override
public void say() {
System.out.println("来自X类的输出 say");
}
}
//第二种实现类
public class TextY implements ClickA {
@Override
public void souTime() {
System.out.println("来自Y类的输出 souTime");
}
ClickB mClickB() {
return new ClickB() {
@Override
public void say() {
}
};
}
}
从实现的观点上来看,两种都没有问题,都可以正常运行,当我们碰到具体的问题的时候,我们才可以决定是用单一类好,还是用内部类比较合理,从上述代码可能并不能很好的看出内部类设计的意义,我们来看下面这段代码如果我们把两个定义的接口换成具体的类(比如我们定义了一个普通类和一个抽象类)
//抽象类
public abstract class TestE {
//这里有些方法 .....
.....
}
//普通类
public class TestD {
// .....这里有些方法
}
//实现类 这里我们TestZ 继承了TestD 以后,我还想继承TestE
//怎么办,这个时候只有采用内部类的形式来实现啦,这也是java设计
//内部类的意义 (以下是匿名内部类的形式)
public class TestZ extends TestD {
TestE makeE() {
return new TestE() {
};
}
}
闭包与回调
闭包的概念:
闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域,通过这个定义我们可以得出,内部类是面向对象的闭包,因为它不仅包含外围类的对象的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有成员,包括私有的。
回调:
java比较受人争议的点是,没有包含类似指针的机制来允许回调,通过回调使对象能够携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象,但是这里有一个问题,如果回调是通过指针来实现的,那么就只能寄希望于程序员不会误用该指针,显然这个问题是不太好控制的,考虑到此java在语言中并没有包含指针,而是采用内部类提供闭包的功能来解决这个问题的,它比指针更灵活,更安全。
内部类的标识符:
每个类都会产生一个.class文件,其中包含了如何创建该类型对象的全部信息,这是java约定好的,因此内部类也一定会产生一个.class的文件以包含创建该类型对象的全部信息,这些类文件的命名有严格的规则,外围类的名字加上 “$”,再加上内部类的名字,如果内部类是匿名的,编译器会简单的产生一个数字作为其标识符,嵌套的内部类是继续在“$”后面跟上类名即可,这是java标准的命名规则。虽然简单,但是很健壮。