可以将一个类的定义放在另一个类的定义的内部,这就是内部类。
内部类的作用:
1、内部类可以很好的实现隐藏
2、内部类拥有外围类的所有元素的访问权限
3、可以实现多重继承
4、可以避免接口中的方法和同一个类中的方法同名的问题
关于以上几个作用,分别举几个例子说明一下:
1、平时我们对类的访问权限,都是通过类前面的访问修饰符来限制的,一般的非内部类,是不允许有 private 与protected权限的,
但内部类可以,所以我们能通过内部类来隐藏我们的信息。
public interface InterfaceTest
{
void test();
}
package insidecategory;
public class Example {
private class InsideClass implements InterfaceTest
{
public void test()
{
System.out.println("这是一个测试");
}
}
public InterfaceTest getIn()
{
return new InsideClass();
}
}
package insidecategory;
public class TestExample {
public static void main(String args[])
{
Example a=new Example();
InterfaceTest a1=a.getIn();
a1.test();
}
}
从这段代码里面我只知道Example的getIn()方法能返回一个InterfaceTest 实例但我并不知道这个实例是这么实现的。而且由于
InsideClass 是private的,所以我们如果不看代码的话根本看不到这个具体类的名字,所以说它可以很好的实现隐藏。同样可以注意
到在getIn方法中有一个向上转型的过程。
2、可以无条件地访问外围类的所有元素
public class TagBean {
private String name="liutao";
private class InTest
{
public InTest()
{
System.out.println(name);
}
}
public void test()
{
new InTest();
}
public static void main(String args[])
{
TagBean bb=new TagBean();
bb.test();
}
}
从上面的例子可以看到,获得了内部类的对象之后,可以访问内部类的属性,哪怕是private属性都可以访问。
3、可以实现多重继承。这个特性应该是最重要的一个特性了。正是由于他的存在使得Java的继承机制更加完善。大家都知道Java只
能继承一个类,它的多重继承在我们没有学习内部类之前是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实
现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类。
基类A:
public class Example1 {
public String name()
{
return "liutao";
}
}
基类B:
public class Example2 {
public int age()
{
return 25;
}
}
子类:
public class MainExample
{
private class test1 extends Example1
{
public String name()
{
return super.name();
}
}
private class test2 extends Example2
{
public int age()
{
return super.age();
}
}
public String name()
{
return new test1().name();
}
public int age()
{
return new test2().age();
}
public static void main(String args[])
{
MainExample mi=new MainExample();
System.out.println("姓名:"+mi.name());
System.out.println("年龄:"+mi.age());
}
}
从上面的例子可以看出,内部类的方法间接的实现了多继承,使得子类同时具有了A、B两个基类的方法。也许你觉得这种设计有点
多余,因为通过接口也可以很好的实现,但是需要注意的是,使用接口的话需要实现接口中的全部方法,包括一些我们不想去实现
的方法,造成了多余,因此也不是最便利的方式。
4、如果一个类要继承一个类,同时还要实现一个接口,如果这两者中有重复名称的话,会造成误解,究竟是继承自父类还是接口中
方法的实现呢?使用内部类可以很好的解决这个问题。
public interface Incrementable
{
void increment();
}
public class MyIncrement {
public void increment()
{
System.out.println("Other increment()");
}
static void f(MyIncrement f)
{
f.increment();
}
}
以上分别是一个接口和一个待继承的父类。利用内部类的方法,可以很好的处理这个问题:
public class Callee2 extends MyIncrement
{
private int i=0;
private void incr()
{
i++;
System.out.println(i);
}
private class Closure implements Incrementable
{
public void increment()
{
incr();
}
}
Incrementable getCallbackReference()
{
return new Closure();
}
}
Ps:在开发中,可以利用匿名内部类结合抽象工厂的方式优化工厂模式,例子如下:
服务类接口:
public interface Cycle {
public void make();
}
抽象工厂接口:
public interface CycleFactory {
public Cycle getCycle();
}
服务类实现A:
public class Unicycle implements Cycle {
private Unicycle() {
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("Unicycle is made.");
}
public static CycleFactory factory = new CycleFactory() {
@Override
public Cycle getCycle() {
// TODO Auto-generated method stub
return new Unicycle();
}
};
}
服务类实现B:
public class Bicycle implements Cycle {
private Bicycle() {
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("Bicycle is made.");
}
public static CycleFactory factory = new CycleFactory() {
@Override
public Cycle getCycle() {
// TODO Auto-generated method stub
return new Bicycle();
}
};
}
服务类实现C:
public class Tricycle implements Cycle {
private Tricycle() {
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("Tricycle is made.");
}
public static CycleFactory factory = new CycleFactory() {
@Override
public Cycle getCycle() {
// TODO Auto-generated method stub
return new Tricycle();
}
};
}
测试类:
public class CycleFactoryTest {
@Test
public void getCycle() {
Unicycle.factory.getCycle().make();
}
}
在这个例子中,服务类的实现类的构造方法被私有化了,不能够直接构建服务实现类的对象,只能够通过工厂来获取。在每一个服
务类实现中都有一个静态的工程对象,并采用匿名内部类的方式进行分别实例化,通过其getCycle方法获得具体的服务类对象。