1 基础
1.1 链接到外部类
内部类能访问其他外围对象的所有成员,不需要任何特殊的条件,还拥有其他的外围元素的访问权(包括private)。
一个内部类无论嵌套多少层,它都能透明地访问所有它所嵌入的外围类的所有成员。
1.2 使用.this 与.new
对外部对象的引用: 外部类名称.this;
public class InnerClass {
private String name;
class Inner {
Inner() {
System.out.println(InnerClass.this.name);
}
}
}
创建某内部类对象: 外部类对象的引用.new 内部类名称()(不必也不能声明为, 外部类对象的引用.new 外部类名称.内部类名称(););
class Client2 {
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
InnerClass.Inner inner = innerClass.new Inner();
}
}
2 分类
2.1 常规内部类
普通内部类不能有static数据和static字段(非静态嵌套类与外部类的对象关联),也不能包含嵌套类。
2.2 局部内部类
作用:1)实现了某类型的接口,于是可以创建并返回对其引用;2)创建一个类来辅助你的解决方案,但不希望这个类是公共可用的。
public interface Cpu {
void run();
}
public class Computer {
public Cpu getCpu() {
class M2Cpu implements Cpu {
@Override
public void run() {
System.out.println("M2芯片速度超快");
}
}
return new M2Cpu();
}
public static void main(String[] args) {
Computer macbookPro = new Computer();
Cpu cpu = macbookPro.getCpu();
cpu.run();
}
}
2.3 匿名内部类
没有名字的内部类。使用前提,必须继承一个父类或实现一个接口。
使用局部内部类和匿名类能实现的功能基本一致,类使用局部内部类的目标是想在这个局部不止一处,创建这个局部内部类对象。
2.4 静态嵌套类
完全属于外部类本身,而不属于外部类的某个对象;
可以包含静态成员,也可包含非静态成员;
不可访问外部类的实例成员,只能访问外部类类成员,其实例方法也不能访问外部类的实例成员;
顶级类不能用static修饰;
创建静态内部类实例:1)非外部类中:外部类名.内部类名 name = new 外部类名.内部类名(); 2)在外部类中: 内部类名 name = new 内部类名();
2.4.1 接口内部的类
放到接口中的任何类都自动地是public 和 static。可以在其内部类中实现其外围接口。
用途:创建某些公共代码,使得它们可以被某个接口的所有不同实现所共用。
/**
* 喇叭
*/
public interface Horn {
void play();
//频道
class Frequency {
static void apply() {
System.out.println("申请频道的方法【所有实现该接口的喇叭的频道申请方法一致】");
}
}
}
public class M5Horn implements Horn{
@Override
public void play() {
System.out.println("播放声音——来源M5播放器");
}
public M5Horn() {
Horn.Frequency.apply();//申请频道
}
public static void main(String[] args) {
M5Horn m5Horn = new M5Horn();
m5Horn.play();
}
}
图 接口内部类示例运行结果
3 扩展
3.1 内部类向上转型
内部类——某个接口的实现——能够完全不可见,并且不可用。所得到的只是指向基类或接口的引用,能方便地隐藏实现细节。
public interface Worker {
void makeMoney();
}
public class Company {
private class ProgrammerWorker implements Worker {
@Override
public void makeMoney() {
System.out.println("努力搬砖");
}
}
public class AnalystWorker implements Worker {
@Override
public void makeMoney() {
System.out.println("写研报");
}
}
public Worker getProgrammerWorker() {
return new ProgrammerWorker();
}
public Worker getAnalystWorker() {
return new AnalystWorker();
}
public static void main(String[] args) {
Company bigCompany = new Company();
Worker programmerWorker = bigCompany.getProgrammerWorker();
Worker analystWorker = bigCompany.getAnalystWorker();
programmerWorker.makeMoney();
analystWorker.makeMoney();
}
}
3.2 内部类继承
在生成构造器时,需要传递一个指向外围类对象的引用,此外,必须在构造器内使用如下语法: 基类的外部类对象.super();
public class Peripheral {
class Inner {}
}
public class Export extends Peripheral.Inner{
public Export(Peripheral peripheral) {
peripheral.super();
}
public static void main(String[] args) {
Peripheral peripheral = new Peripheral();
Export export = new Export(peripheral);
}
}
3.3 内部类覆盖
当继承一个含有内部类的基类的时候,其基类的内部类不会被继承,其导出类的内部类和基类的内部类是完全独立的实体,各自在自己的命名空间内;
当然,可以明确的继承某个内部类。
4 用途
1)解决“多重继承”的问题,内部类能实现多重继承抽象类或具体类;
2)内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外部类对象的信息相互独立;
3)在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类;