前言
除了前面介绍,内部类还有一些更高级的用法,下面就简单的介绍一下
接口内部类
内部类除了可以定义在类的内部,也可以定义在接口里面,用法与类类似
// Move.java
public interface Move {
void run();
void walk();
class Run {
public void move() {
System.out.println("run");
}
}
class Walk {
public void move() {
System.out.println("walk");
}
}
}
// AnimalMoveImpl.java
public class AnimalMoveImpl implements Move {
@Override
public void run() {
new Run().move();
}
@Override
public void walk() {
new Walk().move();
}
}
多层嵌套内部类访问外围类成员
内部类无论嵌套了多少层,内部类都是可以无条件的访问外部的成员,包括private
public class MultiInner {
private int val = 0;
class Inner1 {
{
System.out.println(val);
}
class Inner2 {
{
System.out.println(val);
}
class Inner3 {
{
System.out.println(val);
}
}
}
}
}
内部类继承
这是一个比较有意思的事情
NOTE: 这里说的内部类继承不是内部类继承其他类,而是其他类继承内部类
class WithInner {
class Inner {}
}
public class InheritInner extends WithInner.Inner {
}
在想象中应该是这样写,没问题,但是如果在ide中敲代码,编译器会报错
No enclosing instance of type 'xxx.xxx.xxx.WithInner' is in scope
意思为没有封闭类型的WithInner类型,在ide会提示一种方案是将Inner改为静态内部类,这样确实可以解决问题,但是如果不能用静态内部类呢?
试想一下为什么静态内部类可以,而成员内部类会报错,这两者有什么区别?
回头看一下发现,成员内部类在创建的时候是要依赖外部类的实例对象,但是在第三方类继承内部类的时候,没有外部类对象,这样就无法构成闭环,所以报错。解决办法也很简单,在构造第三方类的时候,手动提供一个外部类对象,并对其初始化即可
public class InheritInner extends WithInner.Inner {
InheritInner(WithInner wi) {
wi.super();
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi);
}
}
内部类能被覆盖吗?
你觉得呢?
分析一下,内部类(以成员内部类来说)依赖于外部类,被编译器编译成WithInner$Inner.class
,假如说有个WithInner
的子类SubWithInner
包含了一个同名的Inner
类,这个会覆盖父类中的Inner吗?子类中的Inner被编译成SubWithInner$Inner.class
这明显与父类中的类名不一样。所以理论上是不会覆盖的。实践一下!
// Egg.java
public class Egg {
private Yolk y;
protected class Yolk {
public Yolk() {
System.out.println("Egg.Yolk");
}
}
public Egg() {
System.out.println("new egg()");
y = new Yolk();
}
}
// BigEgg.java
public class BigEgg extends Egg {
public class Yolk {
public Yolk() {
System.out.println("BigEgg.Yolk");
}
}
public static void main(String[] args) {
new BigEgg();
}
}
new egg()
Egg.Yolk
从输出结果来看,确实没有覆盖,所以,内部类是不会像方法一样被覆盖,但是,如果手动继承那就另说
关于内部类的详细文章可以参考目录 [smxknife's Java内部类]