1.什么时候使用内部类
场景:
当一个事物的内部还有一个部分需要完整的结构(属性和行为)去描述,这个内部的完整结构就只为外部事物提供服务,那么这个内部结构就使用内部类。
例子:
人类都有心脏,人类本身需要属性和行为去描述;人类内部的心脏也需要心脏特殊的属性和行为去描述,心脏就可以定义为内部类。
格式:
class A {
class B {
}
}
分类:
(1)成员内部类:静态 和 非静态
(2)局部内部类
(3)匿名内部类(重点)
2.静态成员内部类
格式:
直接在内部类的定义上加上 static 关键字
public class A{
static class B{
}
}
注意:
(1)内部类可以定义 属性、方法、构造等
(2)静态内部类可以被 final 或者 abstract 修饰;被 final 修饰之后不能被继承;被 abstract 修饰后不能 new
(3)静态内部类 不能调用 外部类的 非静态成员(静态不能调用非静态 原则)
(4)内部类还可以被 4 中权限修饰符修饰
调用方式:
外部类.内部类 对象名 = new 外部类.内部类()
3.非静态成员内部类
格式:
public class A{
class B{
}
}
注意:
(1)内部类可以定义 属性、方法、构造等
(2)非静态内部类可以被 final 或者 abstract 修饰;被 final 修饰之后不能被继承;被 abstract 修饰后不能 new
(3)内部类还可以被 4 中权限修饰符修饰
调用方式:
外部类.内部类 对象名 = new 外部类().new 内部类()
4.局部内部类
使用场景:
可以定义在 方法中、代码块中、构造中等
格式:
public class People{
public void eat() {
class Heart{
public void jump() {
System.out.println("我是局部内部类");
}
}
}
}
特点:
1.局部内部类不能被 new
2.局部内部类嵌套在方法、代码块、构造中,不能有权限修饰符,他的作用域限制在方法中
实际使用:
1.接口类 作为 方法参数和返回值
传递实际参数时,需要传递接口的 实现类对象,因为接口是抽象类不能被 new
返回对象时,仍然需要返回接口的 实现类对象,接收返回值时 需要 接口类来接受(多态)
2.抽象类 作为 方法参数和返回值
抽象类 传递实际参数时,传递的时 子类对象,作为返回值类型返回,实际返回的时子类对象(多态)
3.普通类 作为 方法参数和返回值
传递和返回的都是自身类的对象。
4.局部内部类的实际操作
public interface USB{
void open();
}
public calss Test01{
public static void main(String[] args) {
USB usb = method();
usb.open();
}
public static USB method() {
// 创建局部内部类
class Mouse implements USB() {
@override
public void open() {
System.out.println("鼠标打开");
}
}
return Mouse; // 返回局部内部类,因为局部内部类是USB接口类的一个实现类
}
}
5.匿名内部类
所谓的匿名内部类,可以理解为没有显示声明出类名的内部类
问题描述:
我们想要实现接口,简单实用一次抽象方法,我们就需要创建一个实现类,实现这个接口,重写抽象方法,还要new 实现类对象,所以我们在想如果单纯的实用接口中的方法,能否简化?
格式:
// 匿名对象格式
new 接口/抽象类() {
重写方法
}.重写的方法();
===========================================================================================
// 非匿名方式写法
类名 对象名 = new 接口/抽象类() {
重写方法
}
对象名.重写的方法();
// 创建接口USB
public interface USB{
void open();
void close();
}
// 实现类
public class Main{
public static void main(String[] args) {
// 定义匿名内部类
new USB() {
@override
public void open() {
System.out.println("USB打开了");
}
@override
public void close() {
System.out.println("USB关闭了");
}
}.open(); // 调用方法 .open之前的全部是匿名类对象
}
}
// 这种形式一次只能调用一个方法
匿名内部类/抽象类 在编译的时候已经隐式的生成了,在.class文件中存在。
使用场景:
1.当简单调用一次接口中的方法,我么就可以使用匿名内部类
2.将一种格式代表实现类对象 或者 子类对象来看待,来学习
3.匿名内部类会自动编译生成