内部类
Posted zachyoung
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内部类相关的知识,希望对你有一定的参考价值。
1、概念:
按是否是成员来划分
-
嵌套类( Nested Class )
-
静态嵌套类
-
实例内部类
-
-
局部类 ( Local Class )
-
局部内部类
-
匿名内部类
-
package InnerClass;
// Computer 是个外部类 它对应的 字节码文件是 Computer.class
public class Computer {
?
// 直接在 外部类 的 类体括号中声明的 类 就是 嵌套类 ( Nested Class )
// 嵌套类 也被称作 成员内部类
?
// 有 static 修饰的 嵌套类 也被称作 静态嵌套类 或 静态内部类
static class Brand {
?
// 对应的字节码文件名称 Computer$Brand.class
?
}
?
// 没有 static 修饰的 被称作 非静态嵌套类 或 非静态内部类 或 实例嵌套类 或 实例内部类
class Mainboard { // 主板
// 对应的字节码文件名称 Computer$Mainboard.class
}
?
public void show() {
// 局部类
class Printer {
// 对应的字节码文件名称 Computer$1Printer.class
}
?
Printer printer = new Printer();
// ........
?
}
public void welcome() {
// 匿名内部类
Object object = new Object(){
?
};
System.out.println(object.getClass());
}
?
}
?
2、声明方式
静态内部类
对于嵌套类来说 使用 外部类类名.内部类类名 来 指定变量类型
Computer.Brand = new ComputerBrand();
实例内部类
Computer.Mainboard mainboard = new Computer().new Mainboard();
对于局部类来说 只能在其作用域内部直接使用其类名来声明
3、字节码文件
嵌套类字节码文件名称 外部类名称$嵌套类名称.class
Computer$Brand.class
局部类字节码文件名称 外部类$N局部类名称.class
Computer$1Printer.class
4、匿名内部类
-
不能显式指定类名
-
不能显式声明构造方法
-
但是创建匿名类时,的确会调用父类指定的构造方法
5、匿名内部类的作用
-
使用匿名类 实现接口 并创建该类的实例 【最常见的应用】
package InnerClass;
?
/**
* 1、使用匿名类 实现接口 并创建该类的实例 【最常见的应用】
* */
public class AnnoymousClassTest {
public static void main(String[] args) {
?
// 声明 Flyable 类型的引用变量 并赋予 null
Flyable f = null; // 编译时类型 Flyable
?
// f = new Flyable(); // 接口都没有构造方法 不能实例化
// 形式上 似乎是通过 new 关键字 创建 Flyable 接口的 实例【尸体】
// 本质上 创建了一个实现了 Flyable 接口的匿名类的实例 【借尸还魂】
?
f = new Flyable() { // 匿名类开始 【魂】
-
创建继承了某个抽象类并实现了所有抽象方法的匿名类实例
package InnerClass;
?
/**
* 1、创建继承了某个抽象类并实现了所有抽象方法的匿名类实例
* */
public class AnnoymousClassTest2 {
public static void main(String[] args) {
?
Human h = null;
?
// h = new Human(); // 抽象类有构造 但不能实例化
?
?
h = new Human("张三"){ // 没有无参构造
-
创建继承了某个具体类的匿名类实例
package InnerClass;
?
/**
* 1、创建继承了某个具体类的匿名类实例
* 2、可以在匿名类中重写被继承类中的方法
* */
public class AnonymousClassTest3 {
public static void main(String[] args) {
?
Aircraft a = new Aircraft();
a.fly();
a.travel();
?
System.out.println("~~~~~~~~~~~");
?
Aircraft b = new Aircraft(){};
System.out.println(b.getClass());
?
Aircraft c = new Aircraft(){
// 在匿名类中声明实例变量
String name = "航天飞机";
-
创建继承了某个具体类的匿名类实例
package InnerClass;
?
import java.lang.reflect.Constructor;
?
/**
* 1、创建继承了某个具体类的匿名类实例
* 2、可以在匿名类中重写被继承类中的方法
* */
public class AnonymousClassTest4 {
public static void main(String[] args) {
?
Cloneable c = new Cloneable() {
// 什么都不写
};
System.out.println(c);
?
Class<?> clazz = c.getClass();
?
Constructor<?>[] constructors = clazz.getConstructors();
?
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
?
}
}
?
6、手机类测试内部类
在实例内部类中 可以使用 外部类类名.this 来引用 外部类的当前实例
package InnerClass;
?
?
public class CellPhone {
?
public String brand = "华为";
?
public class Screen {
?
String brand = "京东方";
public void show() {
// 在实例内部类中 使用 this 表示当前类的当前实例 Screen的 实例
System.out.println("外部:" + CellPhone.this.brand + "内部:" + this.brand);
}
?
public CellPhone getOuter() {
// 在 实例内部类中 可以使用 外部类类名.this 来引用 外部类的当前实例
return CellPhone.this;
}
?
}
?
}
package InnerClass;
?
public class CellPhoneTest {
public static void main(String[] args) {
// 引用 cellphone 指向了 CellPhone 类型的实例
// CellPhone cellPhone = new CellPhone();
?
// screen 指向 Screen 实例
// CellPhone.Screen screen = new CellPhone().new Screen();
?
// 创建 实力内部类的实例
CellPhone.Screen screen = new CellPhone().new Screen();
System.out.println(screen);
?
screen.show();
?
System.out.println(screen.brand);
?
CellPhone cellPhone = screen.getOuter();
System.out.println(cellPhone);
?
?
}
}
以上是关于内部类的主要内容,如果未能解决你的问题,请参考以下文章