os:内部内的重点是匿名内部内,成员内部内和局部内部内比较简单,就不陈述了。
匿名内部类
谁没有名字:匿名内部类指的是接口的实现类 或者 抽象类的子类没有名字。
前提:
1)必须要有一个接口、抽象类(普通类也可以,但是方法不会强制重写,不建议)
2)格式:
new 接口/抽象类(){
//复写抽象方法
}
3)本质:匿名内部类的本质其实是一个接口的实现类【对象】,或者抽象类的子类【对象】。
public abstract class Animal {
public abstract void eat();
}
public class Demo2 {
public static void main(String[] args) {
//创建Animal的子类对象
new Animal(){
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}.eat();
//Animal a接收Animal的子类对象。 这是多态的体现
Animal a = new Animal(){
@Override
public void eat() {
System.out.println("狗吃骨头");
}
};
a.eat();
a.eat();
}
}
匿名内部类的实际运用
使用场景:
在实际运用中,如果方法的参数是父类类型,那么调用方法时可以传递子类对象,但是为了图省事不想写子类,那么这个时候可以使用匿名内部类。
public class Demo2 {
public static void main(String[] args) {
//调用方法,传递Animal子类对象
feed(new Animal() {
@Override
public void eat() {
System.out.println("够吃骨头");
}
});
//调用方法,传递Animal子类对象
Animal a = new Animal() {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
};
feed(a);
}
//养动物
public static void feed(Animal a){
a.eat();
}
}
综合案例
1.写一个Usb接口,要求有通电、加载驱动程序、运行三个方法。
2.定义一个UseMouse鼠标类,实现Usb接口,复写三个方法
3.定义一个UsbKeyBoard键盘类,实现Usb接口,复写三个方法
4.写一个Computer电脑类,定义一个useUsb的方法,要求既能接收鼠标也能接收加键盘
把Usb作为方法的参数即可
5.写一个测试类,创建电脑对象,调用useUsb方法
//定义一个USb的接口:
//相当于指定了一个规则
public interface Usb {
public void power();
public void loadDriver();
public void run();
}
//定义鼠标的类
public class UsbMouse implements Usb {
@Override
public void power() {
System.out.println("鼠标通电");
}
@Override
public void loadDriver() {
System.out.println("加载鼠标的驱动程序");
}
@Override
public void run() {
System.out.println("鼠标运行");
}
}
public class UsbKeyBoard implements Usb {
@Override
public void power() {
System.out.println("键盘通电");
}
@Override
public void loadDriver() {
System.out.println("加载键盘的驱动程序");
}
@Override
public void run() {
System.out.println("键盘运行");
}
}
public class Computer {
//使用Usb接口,
//对于电脑来说,并不关心具体是哪一个外接的设备。
// 只要符合Usb规范都可以的
public void useUsb(Usb u){
u.power();
u.loadDriver();
u.run();
}
}
//测试类
public class Demo4 {
public static void main(String[] args) {
//创建电脑对象
Computer com = new Computer();
//创建鼠标对象
UsbMouse mouse = new UsbMouse();
//调用电脑的方法,把鼠标传进去
com.useUsb(mouse);
System.out.println("--------------------");
UsbKeyBoard keyBoard = new UsbKeyBoard();
com.useUsb(keyBoard);
System.out.println("--------------------");
//让电脑使用U盘
com.useUsb(new Usb() {
@Override
public void power() {
System.out.println("U盘通电");
}
@Override
public void loadDriver() {
System.out.println("U盘加载驱动程序");
}
@Override
public void run() {
System.out.println("U盘运行");
}
});
}
}
Lambda表达式
在JDK8以前,使用匿名内部类时,受限于语法格式,必须创建父类\接口的子类对象,再复写抽象方法,这系列动作比较繁琐。从JDK8之后使用Lambda表达式可以对匿名内部类进行简化。
使用Lambda的步骤
Lambda表达式的使用是由条件的,必须要有一个【函数式接口】,在接口中只能有一个抽象方法。
@FunctionalInterface //标记这个接口是函数式接口
public interface Inter{
public void show();
}
再写一个方法,把方法的参数写成函数式接口,调用方法时就可以传递Lambda表达式
public class Demo5{
public static void main(String[] args){
//匿名内部类写法
method(new Inter(){
public void show(){
System.out.println("Inter的show方法执行了");
}
});
//Lambda表达式
method(
()->{
System.out.println("Inter的show方法执行了");
}
);
}
//把方法的参数写成函数式接口
public static void method(Inter in){
in.show();
}
}
Lam
bda表达式的格式
//1. Lambda标准格式
(参数类型1 参数名1,参数类型2 参数名2) -> { 方法体; return 返回值; }
//2. Lambda省略格式,省略参数数据类型
(参数名1,参数名2) -> { 方法体; return 返回值; }
//3. Lambda省略格式,{}中的代码只有一条语句,那么大括号可以省略、rerturn和分号都要省略
(参数名1,参数名2) -> 返回值
//4. Lambda省略格式,参数只有一个时,()可以省略
参数名 -> 返回值
-----------------------------------------------
Lamdba案例
定义一个函数式接口Inter
public interface Inter {
public void printMsg(String s);
}
在测试类中定义一个使用函数式接口的方法method,并测试类中调用方法method,分别按照匿名内部类、Lambda表达式标准写法、Lambda省略写法传递参数。
public class Demo8 {
//把Inter作为方法的参数
public static void method(Inter in){
in.printMsg("想你的夜");
}
public static void main(String[] args) {
//调用方法,传递匿名内部类
method(new Inter() {
@Override
public void printMsg(String s) {
System.out.println(s);
}
});
//调用方法,传递Lambda表达式,标准格式
method((String s)-> {
System.out.println(s);
}
);
//调用方法,传递Lambda表达式,省略数据类型
method((s)-> {
System.out.println(s);
});
//调用方法,传递Lambda表达式,省略大括号
method((s)-> System.out.println(s));
//调用方法,传递Lambda表达式,省略参数的小括号
method(s -> System.out.println(s));
//扩展:当Lambda表达式所做的事情,正好可以用一个方法来代替时。
//可以使用方法引用,可以认为是省略了Lamdab的参数
//格式:【对象名::方法名】 或者 【类名::方法名】
method(System.out::println);
}
}