亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

<table id="w4cb5"></table>
<menuitem id="w4cb5"><small id="w4cb5"></small></menuitem>
  • <samp id="w4cb5"><small id="w4cb5"></small></samp>
    <var id="w4cb5"><label id="w4cb5"><strike id="w4cb5"></strike></label></var><var id="w4cb5"><label id="w4cb5"><acronym id="w4cb5"></acronym></label></var><table id="w4cb5"><tbody id="w4cb5"><acronym id="w4cb5"></acronym></tbody></table>
    為了賬號安全,請及時綁定郵箱和手機立即綁定

    02-方法引用、構造器引用、數組引用

    標簽:
    Java

    通过 lambda 表达式,我们可以更加优雅的替代匿名内部类,生成一个函数式接口的实例,使我们的编码更加简洁。
    这篇文章进一步介绍Java8的新特性,可以让我们的编码相对于 lambda 表达式更为简洁。
    分别是:方法引用构造器引用还有数组引用

    说白了就是借用别人的轮子

    提示:
    这篇文章结合函数式接口lambda表达式进行讲解,Demo中应用了一些Java内置的函数式接口,比如 BiConsumer<T, U>、BinaryOperator<T>、BiFunction<T, U, R>等等。
    还不熟悉这个这两个特性,或者对一些Java内置的函数式接口不熟悉的,请看先阅读 01-函数式接口和 lambda 表达式

    若想了解java8其它新特性,请到 00-java8常用新特性文章索引 阅读。

    1 方法引用

    1.1 方法引用是什么

    如果已经有其他类的某一个方法实现了 函数式接口抽象方法需要实现的代码逻辑(lambda 体),可以通过方法引用,直接引用该类已经实现的方法。

    简单地讲,只要满足以下条件,即可使用方法引用

      1. 参数列表一样
      1. 返回值一样
      1. lambda体的代码逻辑和目标类成员方法的代码逻辑一样

    1.2 方法引用的格式

    使用**::**(双冒号)将类名或者对象名和方法名分隔开。

    对象::实例方法名
    类名::实例方法名
    类名::静态方法名

    1.3 方法引用怎么用

    1.3.1 对象::实例方法名

    对象::实例方法名 Demo

    
    
    /**
     * Description: 运算类
     *
     * @author Xander
     * datetime: 2020/9/1 0:14
     */
    public class Calc {
    
        /**
         * 加法运算,对象::实例方法名 时可以使用
         *
         * @param x
         * @param y
         * @return
         */
        public int add(int x, int y) {
            return x + y;
        }
    
    
        /**
         * 乘法运算,类名::静态方法名 时可以使用
         *
         * @param x
         * @param y
         * @return
         */
        public static long multi(long x, long y) {
            return x * y;
        }
    }
    
    /**
     * Description: 方法引用简单应用
     *
     * @author Xander
     * datetime: 2020/8/31 23:57
     */
    public class MethodRefTest {
    
        @Test
        public void test00() {
    
            //lambda表达式
            Consumer<String> cLambda = str -> System.out.println(str);
            // 对象::实例方法名
            Consumer<String> cMethRef = System.out::println;
            cLambda.accept("hello Lambda");
            cMethRef.accept("hello Method Reference");
    
        }
    
        @Test
        public void test01() {
            Calc calc = new Calc();
            //lambda表达式
            BinaryOperator<Integer> oprLambda = (x, y) -> x + y;
            // 对象::实例方法名
            BinaryOperator<Integer> oprMethRef = calc::add;
            System.out.println(oprLambda.apply(2, 3));
            System.out.println(oprMethRef.apply(2, 3));
        }
    }
    

    test00、test01两个测试用例运行结果:

    hello Method Reference
    hello Method Reference
    5
    5
    
    

    1.3.2 类名::实例方法名

    类名::实例方法名,这个使用的场景比较特殊,要求第一个参数是实例方法的调用者,剩余的参数都是实例方法的入参,剩余的参数个数可以是0个或者多个。
    提示:目标类的实例方法的参数列表会比函数式接口的抽象方法入参个数少一个,因为第一个参数是实例方法的调用者。

    public class Person {
    
        //姓名
        private String name;
        //年龄
        private long age;
    
        public Person(String name, long age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public long getAge() {
            return age;
        }
    
        public void setAge(long age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    
        /**
         * 打招呼
         *
         * @param p
         */
        public void sayHello(Person p) {
            System.out.println(this.getName() + " say hello to " + p.getName());
        }
    }
    
    public class MethodRefTest {
    ...
        @Test
        public void test02() {
            //lambda表达式
            BiConsumer<Person,Person> bcLambda = (x, y) -> System.out.println(x.getName()+" say hello to "+y.getName());
            // 类名::实例方法名
            BiConsumer<Person,Person> bcMethRef = Person::sayHello;
            bcLambda.accept(new Person("P1",18),new Person("P2",18));
            bcMethRef.accept(new Person("P3",18),new Person("P4",18));
        }
        
        @Test
        public void test03() {
            // 判断两个String是否equals
            //lambda表达式
            BiFunction<String, String, Boolean> bfLambda = (x, y) -> x.equals(y);
            // 类名::实例方法名
            BiFunction<String, String, Boolean> bfMethRef = String::equals;
            System.out.println(bfLambda.apply("a", "b"));
            System.out.println(bfMethRef.apply("a", "a"));
    
            //求 String 的 hashCode
            //lambda表达式
            Function<String, Integer> funcLambda = str -> str.hashCode();
            // 类名::实例方法名
            Function<String, Integer> funcMethRef = String::hashCode;
            System.out.println(funcLambda.apply("a"));
            System.out.println(funcMethRef.apply("a"));
        }
    }
    

    test02、test03 运行结果:

    P1 say hello to P2
    P3 say hello to P4
    false
    true
    97
    97
    

    1.3.3 类名::实例方法名

        @Test
        public void test04() {
            //lambda表达式
            BinaryOperator<Long> bfLambda = (x, y) -> x * y;
            // 类名::静态方法名
            BinaryOperator<Long> bfMethRef = Calc::multi;
            System.out.println(bfLambda.apply(2L, 3L));
            System.out.println(bfMethRef.apply(2L, 3L));
        }
    
        @Test
        public void test05() {
            //lambda表达式
            BinaryOperator<Double> bfLambda = (x, y) -> Math.pow(x,y);
            // 类名::静态方法名
            BinaryOperator<Double> bfMethRef = Math::pow;
            System.out.println(bfLambda.apply(2D, 3D));
            System.out.println(bfMethRef.apply(2D, 3D));
        }    
    

    test04、test05 运行结果:

    6
    6
    8.0
    8.0
    

    2 构造器引用

    2.1 构造器引用是什么

    构造器引用依然是要结合函数式接口进行使用。
    为了简化函数式接口的抽象方法需要实现的代码逻辑(lambda 体),如果lambda体中有返回值,而且返回值类型的构造器参数列表和函数式接口抽象方法的参数列表一致。
    这时,就可以使用构造器引用。

    看定义,应该看得很懵逼,直接看下面的demo。

    2.2 语法格式

    类名::new

    2.3 构造器引用简单使用

        @Test
        public void test06() {
            //通过函数式接口IntFunction 创建 Integer 实例
            //lambda表达式
            IntFunction<Integer> intFuncLambda = i -> new Integer(i);
            // 构造器引用:类名::new
            IntFunction<Integer> intFuncConstRef = Integer::new;
            //lambda表达式生成 函数式接口IntFunction 的实例,执行apply方法后,生成的 Integer 实例
            Integer integerLambda = intFuncLambda.apply(5);
            //构造器引用生成 函数式接口IntFunction 的实例,执行apply方法后,生成的 Integer 实例
            Integer integerConstRef = intFuncConstRef.apply(15);
            System.out.println(integerLambda.intValue());
            System.out.println(integerConstRef.intValue());
        }
    
        @Test
        public void test07() {
            //通过函数式接口BiFunction 创建 Person 实例
            //lambda表达式
            BiFunction<String, Long, Person> bfLambda = (name, age) -> new Person(name, age);
            // 构造器引用:类名::new
            BiFunction<String, Long, Person> bfConstRef = Person::new;
            // lambda表达式生成的Person
            Person personLambda = bfLambda.apply("张三", 20L);
            // 构造器引用生成的Person
            Person personConstRef = bfConstRef.apply("李四", 25L);
            System.out.println(personLambda);
            System.out.println(personConstRef);
        }
    
    

    运行结果:

    5
    15
    Person{name='张三', age=20}
    Person{name='李四', age=25}
    

    3 数组引用

    3.1 是什么

    如果你理解了上面的构造器引用,那理解数组引用的使用就很简单了。
    构造器引用通过函数式接口的抽象方法调用,使用返回值类型中与函数式接口抽象方法的参数列表一致的构造器,创建一个对象。

    数组引用:通过函数式接口的抽象方法调用,将参数作为返回值数组的构造器入参,创建一个数组。

    单看这句话应该还是懵逼,下面看一下使用demo。

    3.2 语法格式

    类名[]:new

    3.3 数组引用简单应用

        @Test
        public void test08() {
            // 通过数组引用,生成 String[] 实例
            //lambda表达式
            Function<Integer, String[]> funcLambda = length -> new String[length];
            // 数组引用:类名[]::new
            Function<Integer, String[]> funcArrayRef = String[]::new;
            // lambda表达式生成的String[]
            String[] arrayLambda = funcLambda.apply(2);
            arrayLambda[0] = "lambda";
            // 数组引用生成的String[]
            String[] arrayArrayRef = funcArrayRef.apply(2);
            arrayArrayRef[0] = "Array Reference";
            System.out.println("lambda生成数组:" + Arrays.toString(arrayLambda));
            System.out.println("数组引用生成数组:" + Arrays.toString(arrayArrayRef));
        }
    

    运行结果:

    lambda生成数组:[lambda, null]
    数组引用生成数组:[Array Reference, null]
    

    方法引用,构造器引用,数组引用都需要结合函数式接口进行使用,当执行函数式接口的抽象方法时,其实调用的是引用类的方法逻辑或者构造器的逻辑,这就是典型的借轮子
    使用简单,设计灵巧,但要达到熟练程度,还需要多加理解,学以致用。

    點擊查看更多內容
    TA 點贊

    若覺得本文不錯,就分享一下吧!

    評論

    作者其他優質文章

    正在加載中
    JAVA開發工程師
    手記
    粉絲
    11
    獲贊與收藏
    8

    關注作者,訂閱最新文章

    閱讀免費教程

    • 推薦
    • 評論
    • 收藏
    • 共同學習,寫下你的評論
    感謝您的支持,我會繼續努力的~
    掃碼打賞,你說多少就多少
    贊賞金額會直接到老師賬戶
    支付方式
    打開微信掃一掃,即可進行掃碼打賞哦
    今天注冊有機會得

    100積分直接送

    付費專欄免費學

    大額優惠券免費領

    立即參與 放棄機會
    微信客服

    購課補貼
    聯系客服咨詢優惠詳情

    幫助反饋 APP下載

    慕課網APP
    您的移動學習伙伴

    公眾號

    掃描二維碼
    關注慕課網微信公眾號

    舉報

    0/150
    提交
    取消