内部类
一、内部类概述
内部类拥有其外部类所有元素的访问权,构建内部类对象时需要一个指向其外部类对象的引用,如果编译器访问不到这个引用就会报错。
二、内部的创建
如果想要生成对外部类的引用,可以使用this关键字(外部类名点this)。
public class Outside{
void fun(){
System.out.println("Outside.fun()");
}
public class Inner{
public Outside creatOut(){
return Outside.this;//生成对外部类Outside的引用
}
}
public Inner inner(){
return new Inner();
}
public static void main(String[] args){
Outside os = new Outside();
Outside.Inner osi = os.inner();//通过调用Outside方法创建内部类Inner对象
Outside.Inner osi2 = os.new Inner();//通过new关键字创建内部类Inner对象
osi.creatOut().fun();//调用内部类creatOut方法得到外部类Outside对象并调用其fun()方法
}
}
注:在拥有外部类对象之前是不可能创建内部类对象的,因为内部类对象会暗地里连接到创建它的外部类对象上(静态内部类除外)。
三、局部内部类
内部类不仅能向上面那样作用在一个类之下,亦可作用与某个方法里或某个判断语句中,称其为局部内部类。
四、匿名内部类
匿名内部类顾名思义就是没有名字的内部类,如果定义一个匿名内部类,并且希望他能使用一个外部类定义的对象,则编译器会要求参数引用是final。
匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备。而且如果实现接口,也只能实现一个接口。
public class Outside{
public Inner creatInner(final float price){
return new Inner(){
private int cost;
{
cost = Math.round(price);
if(cost>100){
System.out.println("cost:"+price);
}
}
};
}
}
注:匿名内部类,return new Xxx()等价于class MyXxx implements Xxx,即匿名内部类表示创建一个继承自Xxx的匿名类对象,这里通过new返回的引用会被自动向上转型为对Xxx的引用。
五、嵌套类
如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为static(嵌套类)。
嵌套类与普通内部类的区别:
1.嵌套类对象没有隐式保存一个对外部类对象的引用,即嵌套类中不能访问非静态的外部类对象。
2.普通内部类不能有static数据和static字段,但嵌套类可以包含这些东西,并且嵌套类能访问外部static数据。
public class A{
static void f(){}
static class B{
static void g(){}
public class C{
void h(){}
g();
f();
}
}
}
以上是多层嵌套类,即最里层能够调用外层所有的方法。
六、接口内部类
正常情况下,不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分存在。
public interface ClassInnerface{
void fun();
class A implements ClassInnerface{
public void fun(){System.out.println("A-fun");}
public static void main(String[] args){
return A.fun();
}
}
}
这样就可在接口中创建一段公共代码,能够使接口的所有不同实现共用。
七、使用内部类后的工厂方法
引入内部类之后,工厂方法会变得更加的美妙:
public interface Service{
void method1();
void method2();
}
public interface ServiceFactory{
Service getService();
}
class A implements Service{
public method1(){System.out.println("method1")}
public method2(){System.out.println("method2")}
//使用匿名内部类创建service工厂
public static ServiceFactory factory =
new ServiceFactory(){
public Service getService(){
return new A();//得到一个service
}
};
}
public class Factories{
public static void serviceConsumer(ServiceFactory sf){
Service s = sf.getService();//得到A服务,并向上转型
s.method1();
s.method2();
}
public static void main(String[] args){
serviceConsumer(A.factory);//A.factory得到service工厂
}
}
八、为什么需要内部类
使用内部类可以得到以下一些特性:
1.能够实现“多重继承”。
2.内部类可以有多个实例,每个实例都有自己的状态信息,并与外部类相互独立。
3.内部类没有“is-a关系”,是一个独立的实体。
4.单个外部类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。