内部类
内部类
描述:内部类定义在类内部的类 本质是类使用需要创建对象
内部类存在的意义:
当目前某个类现在需要一个只能该类使用的类时
1.能修饰类的权限修饰符只能时 默认不写(default) 和公共(public)
2.内部类私有化
解释:
-
正向思考:
- 四种权限修饰符常用来修饰成员 这时候时站在 类的角度在看
- 当用来修饰类时 类的上层是 "包" 此时 只有两种可能本包和其他包
- 默认不写 本包可见 其他包不能使用(不能导包) public 本包和其他包都能用 2个就够用了
-
强制加其他:
- private 站在 包的角度 私有的类 (JAVA)都没法编译,加载类 类没有存在的意义
- protected 站在包的角度 A类想要继承B类 (B类protected) 能继承吗? 不能 虽然protected访问的权限比default大 但是他有一个条件 存在继承关系 (这是类的角度) 也就是说 此时A应该已经是B的子类 现实情况呢 A不是B的子类 所以不能继承 不能protected修饰(修饰了就不能继承了 实际是能继承)
比如: 你 想继承 一个百万富翁的遗产 前提是 你是他的后代 现实是你不是它的后代 所以你不能继承
-
想不被别的类用 那么不能放外面 放里面 不想被其他类使用 那么私有化
语法:
//这是成员内部类的语法
public(或者不写) class 外部类名(){
private class 内部类名(){
}
}
内部类分类
成员内部类
位置:在成员位置的类
局部内部类
位置:方法中的类
public class Test {
public void show() {
int a = 10;
class Inside {//方法中的类
public void show() {
System.out.println("a = " + a);//10
}
}
Inside in = new Inside();//使用只能间接用 类只能在方法中使用
in.show();
}
public static void main(String[] args) {
Test t = new Test();
t.show();
}
}
好处
可以方便内部类直接使用外部参数 省去传参
Tips:
Outer.this.num Inner.this.num num 类似 "路径问题"
因为我们不导包可以 用包名类的形式 使用类
当内部类时public时可以通过传参来实现
public class People {
private String name;
private Heart heart;
public People(String name,Heart heart) {
this.name=name;
this.heart = heart;
}
public void show(){
System.out.println(name+"的心脏"+heart.jumping()+"血型是:"+heart.getBloodType());
}
public static void main(String[] args) {
People p = new People("小明",new Heart("A型") );
p.show();
}
}
匿名内部类
可参考:https://blog.csdn.net/qq_35394434/article/details/111695348
描述:匿名内部类是局部内部内的一个特例
匿名 的"名"重在强调 类名 没有类名 同时直接创建时是一个没有名字的对象
本质:是一个继承了该类的子类匿名对象,或者是一个实现了该接口的实现类匿名对象
特点: 现用 现做 用完后就没了
没有类 创建不了对象 创建了对象没有名字 只能用一次
语法:
//前提是:存在一个类或者抽象类或者接口
new 类名/接口名{
重写方法;
}
public class Outer {
public void method() {
/*
new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
*/
// show();
//--------------------------------
/*
new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
//--------------------------------
*/
Inter i = new Inter() {//多态接受
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
}
}
好处:
省去了实现类的编写
使用匿名内部类时共做了三件事:
1.搞了已知类的子类或者实现类
2.重写了方法
3.造了对象
使用场景:
匿名内部类和正常的实现接口继承父类 使用的区别
- 当实现类确定只使用一次 使用匿名内部类 其他情况正常实现
Lambda表达式
使用条件:
- 有一个接口
- 接口中只能有一个抽象方法
语法:
() -> {} //()表示参数表 放形参 {} 表示方法体 重写的内容
public class EatableDemo {
public static void main(String[] args) {
//在主方法中调用useEatable方法
//匿名内部类
useEatable(new Eatable() {
@Override
public void eat() {
System.out.println("一天一苹果,医生远离我");
}
});
//Lambda表达式
useEatable(() -> {
System.out.println("一天一苹果,医生远离我");
});
}
private static void useEatable(Eatable e) {
e.eat();
}
}
省略规则:
- 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
为啥可以用Lambda:可推导可省略(猜想JAVA的一种思想)
匿名内部类和Lambda的区别
-
所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
-
使用限制不同
- 如果接口中仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
-
实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:对应的字节码会在运行的时候动态生成
推荐适用匿名内部类
Lambda可以在写好匿名内部类的情况下使用Alt+Enter生成