* 方法引用的 4 + 2 种方式 对于类来说,有4种方式 1. 对象引用成员方法 2. 类名引用静态方法 3. super引用父类方法 4. this引用本类方法 对于构造器来说,有2种方法。 1. 类的构造器引用 2. 数组的构造器引用。 1 对象引用成员方法详解 对象引用成员方法 对象名::方法名 */ public class Demo01MethodRef { public static void main(String[] args) { //创建MyClass对象 MyClass myClass = new MyClass(); method(s1 -> myClass.printStr(s1)); method(myClass::printStr);//对象引用成员方法 }
public class MyClass {
public void printStr(String str) {
System.out.println(str.toUpperCase());
}
}
public static void method(PrintAble printAble) { printAble.print("Hello"); } }
public interface PrintAble { void print(String str); }
----------------------------------------------------------------------------------------------
//练习,lambada表达式,匿名内部类,方法的引用 这里总结了一个练习方法,一般的打印输出都能练习到方法的引用,增加应用频率
//对象引用成员方法 lambada自己不重写了。找了个对象,对象里有个方法居然跟自己的抽象方法相似,那么如果目的一致,
就可以把它当作重写的,目的不一致,那么引用后的结果就是对象的成员方法的,如果参数不要了,对象里的方法没有用到该参数,那里面是啥内容,方法引用后就是啥,比如打印hello 算1+1=2. 也算是找到了一个高档方法表达简单方法的途径,只不过该简单方法舍弃了自己的参数,或者歪用了参数。这么想,写抽象接口利用方法的引用和lambada表达式,就是把简单的问题变复杂,直接算1+1=2,我非要创建接口,抽象方法当参数传入成员方法,成员方法调用时再整个类,创个对象,做个成员方法,引用一下。
public class Demo02MethodRef {
public static void main(String[] args) {
//method(s -> System.out.println("使用Lambda表达式手忙脚乱的处理" + s));
//调用的时候,重写了Helper.help
// method( new Helper() {
// @Override
// public void help(String str) {
// System.out.println("使用lambada原理表达式"+str);
// }
// });
method((s) -> System.out.println("使用lambada手忙脚乱的" + s));
// 运行:使用lambada手忙脚乱的处理文件
//注意需要重写的run方法是有参数str的
// a代表有参数,
Assistant a = new Assistant();
// method(s -> System.out.println("使用Lambda表达式手忙脚乱的处理" + s));
method(s -> a.doFile(s));//助手正在井井有条的处理
method(a::doFile);// 助手正在井井有条的处理
//接口作为参数传进来,lambada表达式里是需要重写的抽象方法。然而抽象方法想要做的事和对象的成员方法
//不一致,返回值和参数一致,成员方法把参数抛弃了,该引用也就是重写过程中抛弃了参数,直接执行方法体的内容
// 该方法可以强行造格式,比如写出来HELLOWORLD 。接口:void(String) 传参赋值可以任意赋值,创建一个打印
// Helloworld的类。成员方法 void method(String) 方法体sout(Helloword) 。则本来可以创建对象
//打印类名.method出来,我们可以用lambada表达式这一高档的方法了。(String s)->类名.method(s)
//还可以用方法引用这种高档的方法了。类名;;方法名 至此,好像没有接口方法什么事。那么我们能把接口省
//略直接打印不?注销之后发现并不行。。。。,那么匿名内部类是否可以,我试试
method(new Helper() {
@Override
public void help(String str) {
System.out.println("匿名内部类丢参重写的hello");
}
});
// 试验之后发现可以,不过这个丢参让人一眼就看出来了。不怎么好
}
public static void method(Helper helper) {
helper.help("处理文件");//抽象方法作为参数传入,并没有调用抽象方法,不用重写, 单纯
// 赋值
}
}
//对象的类
ackage cn.itcast.demo06b_对象引用成员方法; public class Assistant { public void doFile(String file) { System.out.println("助手正在井井有条的处理" ); } }
//函数接口
public interface Helper { void help(String str);//接口的抽象方法 }
----------------------------------------------------------------------------------------------------------
2 类名引用静态方法
类名引用静态方法 类名::静态方法 */ public class Demo01MethodRef { public static void main(String[] args) { // method(-10,num ->num>0?num:-num); //在java中,有一个数学工具类,这个类叫做Math,里面有一个静态方法,叫做abs可以直接求出绝对值。 // method(num -> Math.abs(num)); method(-10, Math::abs); method(-10,(int num)->Math.abs(num));
直接引用的工具类。
} public static void method(int num, Calculator c) { int result = c.abs(num); System.out.println(result); } }
//函数接口
public interface Calculator { int abs(int num); }
--------------------------------------------------------------------------------------------
public class Demo02MethodRef { public static void main(String[] args) { //Lambda表达式中的检查规则,如果这个字符串是一个空字符串,那么就返回true //空字符串指的是这个字符串是 null或者这个字符串是一个空白的字符串 method(" fds ", s -> s == null || s.trim().equals("")); //如果不用lambda就只能用匿名内部类 new接口,内部类中重方法 method("fds", new StringChecker() { @Override public boolean checkString(String str) { boolean result = str == null || str.trim().equals(""); return result; } }); method(" ", s -> StringUnits.isBlank(s));//类名引用静态方法,拿到s对s进行操作, // 所要做的正好是s要做的,我可以改,只要是抽象方法的返回值类型,参数类型的方法的类都能引用 // 或者说,只要是该类中的方法,类似重写了接口中的方法,就可以用该格式引用 method(" ",StringUnits::isBlank);// } public static void method(String str, StringChecker checker) { boolean flag = checker.checkString(str); System.out.println("flag:" + flag); } }
//自定义的函数接口,里面写了个检查字符串的方法,
public interface StringChecker { // 函数式接口里面定义一个方法,checkString, 用来检测一个字符串是否符合规则 boolean checkString(String str); }
//新创建的类。类引用静态方法,那么也就是主函数不创建该类的对象呗,不创建对象
//那么也就只能引用静态方法了。只有静态方法能在不创建对象的情况下点出来运行
//接口要引用的类
public class StringUnits { public static boolean isBlank(String s) { return s!=null && s.trim().equals("f"); }
public void method2 (){ System.out.println("我这非静态的方法,成员方法能不能被点出来呢"); }
}
可以看到这个类是点不出来非静态方法的。那么类名引用静态方法格式和对象引用成员方法是一样的,区别就是对象和类的区别。。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
3super引用父类方法
//接口作为参数传入子类方法了,子类没有能力重写,父类重写,没有能力调用,主函数调用。。。
/* super引用父类方法格式: super::父类方法 */ //其调用作用的主函数,里面就是运行了一下子类方法,子类中实现了方法的引用 public class Demo01MethodRef { public static void main(String[] args) { Student stu = new Student(); stu.sayHello(); } }
//函数接口
public interface Greetable { void greet(); }
//父类
public class Person { public void sayHello() { System.out.println("雷猴啊"); } }
//子类 ,子类要用引用,方法中应该有重写接口方法的类似方法,它没有,借父类的sayhello,那么格式。super::sayhello
public class Student extends Person { public void sayHello() { method(() -> System.out.println("你好啊")); method(super::sayHello);//super 中的方法,参数和返回值类型都为空,和接口类型一致 // 那么如果接口方法要做的事情和super中的方法一致,那可以构成方法引用,就是接口中传入的参数 // 对参数直接进行了某些操作 } public static void method(Greetable greetable) { greetable.greet(); } }
---------------------------------------------------------------------------------------------------------------------------------------------------------------
4 this 引用本类方法
*/ main函数调用称为本类的那个类 public class Demo01Ref { public static void main(String[] args) { Man m=new Man(); m.method(); } }
//我是本类。接口传参到类,我自己的类里面有一个方法重写的跟接口中想重写的相似,this::方法名 那么我是不是也可本类名::方法名 上面 有类引用静态方法,然而本类中好像没有静态方法,是不是也可以呢,我试试,然而结果并不可以。。 public class Man { public void beHappy() { System.out.println("买了房子很开心"); //引用rich.buy方法,午餐无返回值 } public void man(Rich rich) { rich.buy(); //接口作为参数传入 } public void method() { man(this::beHappy); } }
//函数接口rich
public interface Rich { void buy(); }
* this引用本类的方法格式: this::方法名 */ public class Demo01Ref { public static void main(String[] args) { Man m=new Man(); m.method(); }
--------------------------------------------------------------------------------------------
4+1(上面是前4个)
* 类的构造器引用 类名::new */ public class Demo01ClassConstrutionRef { public static void main(String[] args) { //构造器的引用 method(Person::new);//对传入的参数进行new操作 // 传入的接口参数为Person类型,要进行new操作。要进行new的操作。 method(new PersonBuilder() { @Override public Person CreatePerson(String name, int age) { return new Ceat("张无忌", 19); } });//用匿名内部类表示的创初始化对象。因不能new 接口对象。 // lanbada表达式 method((name, age) -> new Person(name, age)); /* 参数 参数 {方法体 返回值 } * */ } public static void method(PersonBuilder personBuilder) { Person person = personBuilder.CreatePerson("张无忌", 19); System.out.println(person); } }
//接口,该接口的抽象方法想创建一个对象,那么重写方法就要。。。。 public interface PersonBuilder { //提供一个方法,给我一个姓名和年龄,我就可以创建一个Person对象 Person CreatePerson(String name,int age); }
----------------------------------------------------------------------------------------------------------------------------------
4+2 数组的构造器引用
/* 数组的构造器引用 数据类型[]::new */ public class Demo01ArrayRef { public static void main(String[] args) { method(new ArrayBuilder() { @Override public int[] createArray(int len) { return new int[len]; } }); method(int[]::new); method((len) -> new int[len]); } public static void method(ArrayBuilder arrayBuilder) { int[] arr = arrayBuilder.createArray(10); System.out.println(arr); } }
//函数接口
public interface ArrayBuilder { //提供方法,给我数组长度,根据数组长度创建一个数组 int[] createArray(int len); }