匿名内部类还有哪些缺点?
匿名内部类存在的一个问题是,如果匿名内部类的实现非常简单,例如只包含一个抽象方法的接口,那么匿名内部类的语法仍然显得比较冗余。
解决方法:
可以使用JDK 8中新增的Lambda表达式,这种表达式只针对有一个抽象方法的接口实现,以简洁的表达式形式实现接口功能来作为方法参数。
举例:
public Interface Animal//动物接口
{
void eat();//抽象方法
}
public class Dog implements Animal//狗类实现动物接口
{//
public void eat()//重写方法
{
System.out.println("狗吃骨头");
}
}//
public class Master{
public void feed(Animal a)//传一个接口
{
a.eat();
}
}
public class Test//测试类
{
public static void main(String []args)
{
Master m=new Master();
/*m.feed(new Animal(){//本来应该传new Dog(),但这里运用匿名内部类new 父类名字或者接口的名字,所以按照这样写,需要实现接口中的方法.
public void eat()
{
System.out.println("狗吃骨头");
}
});*/
m.feed(()->{
System.out.println("狗吃骨头");
});
}
}
注意:
接口中有且只有一个抽象方法时才能使用Lamdba表达式代替匿名内部类.
这是因为Lamdba表达式是基于函数式接口实现的,所谓函数式接口是指有且仅有一个抽象方法的接口 Lambda表达式就是Java中函数式编程的体现,只有确保接口中有且仅有一个抽象方法,Lambda表达式才能顺利地推导出所实现的这个接口中的方法。
JDK8之后,接口中可以有default 修饰的默认的方法体,以及static修饰的方法体,它们不算抽象方法,只要接口中有且仅有一个抽象方法即函数式接口
@FunctionalInterface//编译器会帮忙检测下面是否为一个函数式接口
public interface A{
}
interface B{
void show ();
}
interface C{
void show ();
void m();
}
interface D{
void show ();
static void m(){};
}
interface E{
void show ();
default void m(){};
}
Lanmbda表达式
([数据类型 参数名,数据类型 参数名,...]) -> {表达式主体}
①用来向表达式主体内部实现的接口方法传入参数。多个参数之间用逗号分隔,可以省略数据类型,只有一个参数时还可以省略小括号
②表示Lambda表达式箭牌,用来指定参数数据指向,不能省略
③本质就是接口中抽象方法的具体实现。如果只有一条语句,可以省略大括号;在Lambda表达式主体中只有一条return语句时,也可以省略return关键字
public interface NoparNoreturn{//接口
void m1();
}
interface SinglparNoreturn{
void m2(int a);
}
interface MultiparNoreturn{
void m3(int a,int b);
}
interface NoparYesreturn{
int m4();
}
interface SinglparNoreturn{
void m5(int a);
}
interface MultiparNoreturn{
void m6(int a,int b);
}
public class Demo{//测试类
public static void main(String[] args)
{
NoarNoreturn nn=()->{
System.out.println("hello");//匿名重写方法
};
nn.m1();//第一种形式,调用和抽象方法一样的方法名.
yanzheng(()->{//第二种形式
System.out.println("hello");
});
SinglparNoreturn sn=(int a)->{
System.out.println(a);//用Lanmbda表达式实现了接口中方法的重写
};
sn.m2(36);//第三种形式,有参数的
SinglparNoreturn sn1=new QQ();
sn1.m2(66);//这是复杂版的,利用Lanmbda表达式其实就是简化了实现类
MultiparNoreturn mn=()->{
System.out.println(a+b);
};
mn.m3(34,12);
yanzheng1((int a)->System.out.println(a),88);//匿名实现抽象类方法并且简化
NoparYesreturn ny=()->100;//只有一条语句并且是返回值时,可以写成这样.
NoparYesreturn ny=()->{//这是重写的方法体
System.out.println("abc");
return 100;
}
System.out.println(ny.m4());//调用重写的方法体
NoparYesreturn sy=a->a;//只有一个参数时,有一个返回值,可以省略小括号和大括号.
System.out.println(sy.m5(90));
MultiparNoreturn my=(a,b)->a+b;
System.out.println(m6.(12,67));
}
public static void yanzheng(NoparNoreturn nn)//第二种形式的方法
{
nn.m1();
}
public static void yanzheng1(NoparNoreturn nn,int a){
nn.m2(a);
}
}
public class QQ implements SinglparNoreturn{
public void m2(int a){//重写接口的方法
System.out.println(a);
}
}
Lanmbda方法体只有一句表达式时,可以省略大括号
方法引用与构造器的引用
interface MultiparNoreturn{
void m6(int a,int b);
}
public class Demo{
public static void main(String[] args)
{
//Lanmbda表达形式
MultiparNoreturn my=(a,b)->fab(a,b);
//方法引用形式
MultiparNoreturn my1=Demo::fab;//前提是此类的静态方法
System.out.println(my.m6(12,6));
}
public static int fab(int a,int b){
return a*b;
}
}
方法引用求绝对值
public class Math{
public static int abs(int num){
if(num<0)
return -num;
else
return num;
}
}
public interface Calcable{
int cal(int num);
}
public class CalTest{
public static void main(String []args)
{//此为Lanmbda表达形式,但如果有一个类已经实现了
Calcable c=num->{
if(num<0)
return -num;
else
return num;
};
Calcable c=Math::abs;//方法引用的形式
System.out.println(c.cal(-34));
printAbs(-34,num->Math.abs(num));
printAbs(-34,Math::abs);//方法引用
}
public static void printAbs(int num,Calcable c){//如果接口里面有参数,括号里面就有什么参数,另外加一个接口参数
System.out.println(c.cal(num));
}
}
构造器的引用
public class Person{
String name;
int age;
public Person(){
System.out.println("无参构造方法执行了");
}
public Person(String name,int age)
{
this.name=name;
this.age=age;
System.out.println("有参构造方法执行了");
System.out.println(name+" "+age);
}
}
public interface PersonInter{
Person getPerson();//一定要返回一个类的对象
}
interface PersonInter1{
Person getPerson(String name,int age);
}
public class PersonTest{
public static void main(Stirng [] args)
{
PersonInter pi=()->new Person();//Lanmbda表达形式创建一个无参的Person对象
pi.getPerson();
PersonInter1 pi2=Person::new ;
pi2.getPerson("zhangsan",23);
}
}