您的位置 首页 java

「JAVA8」- 神奇的双":"号

看如下一行代码

 public class Car {

    public static Car create(Supplier<Car> supplier){
        return supplier.get();
    }

    public static void main(String[] args) {
        Car car = Car.create(Car::new);
        List<Integer> integers = new ArrayList<>();
        integers.stream().mapToInt(Integer::intValue).sum();
        integers.stream().mapToLong(Long::valueOf).sum();
    }
}  

生成Car对象用Car::new

获取Integer的int值采用Integer::intValue

将Integer转化成Long采用Long::valueOf即可。

你是否会疑惑这个神奇的”::”是什么?

这就是我们Java8中的新特性方法引用。

我们可以用一对冒号 “::”, 通过方法的名字来指向一个方法,可以使语言的构造更紧凑简洁,减少冗余代码。

疑惑,那Car::new返回的是什么呢?是Car对象吗?

 Car car = Car::new; 报错

Supplier<Car> carSupplier = Car::new; 正确  

Car::new 返回的是 Supplier<Car> 对象,生成Car 是carSupplier.get时候初始化。

那Integer::intValue呢?

这里是调用了Integer的iniValue方法。为什么可以这样使用呢?

 //错误示例
int result = Integer::intValue; 

//正确
ToIntFunction<Integer> intFunction = Integer::intValue;  

再来看一个例子

 ToIntFunction<Integer> intFunction = Integer::valueOf;
ToIntFunction<Integer> intFunction2 = Integer::intValue;

这两个都是返回的都是ToIntFunction<Integer>  

JAVA8中”::”把函数变成了参数,传递到函数里面

但是”::”为什么把Car::new转化成了Supplier<Car>,Integer::valueOf转化成了ToIntFunction<Integer>呢?

来看 Supplier

 @FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}  

Supplier有一个get()方法,不需要传入参数返回T对象。

Car的new方法,默认构造方法,不需要传入参数,返回Car对象。

说到这里还不明白的话,看下面这个例子。

 public class Car {

    public static Car generate(){
        return new Car();
    }

    public static void main(String[] args) {
        Supplier<Car> car=  Car::generate;
    }

}  

Car::generate同样是返回的是Supplier<Car>,generate没有参数,返回的是Car对象,刚好跟Supplier符合。

说到这里相信大概大家明白了, “::”将我们的方法转化成了对应的函数式接口

举个例子

ToIntFunction类

 @FunctionalInterface
public interface ToIntFunction<T> {

    /**
     * Applies this function to the given argument.
     *
     * @param value the function argument
     * @return the function result
     */
    int applyAsInt(T value);
}  

参数是T,返回int对象。如果我们要使用”::”该如何做呢?

 public class Car {

    public static int test(int tst){
        return 1;
    }
    public static void main(String[] args) {

        ToIntFunction<Integer>  integerToIntFunction =  Car::test;
    }

}  

我们只要定义一个方法,有一个输入参数,返回参数是int即可。

讲到这里,我们用Java8将List<Integer>转化成List<Long>怎么处理呢?

我们看到stream里面有一个方法

     /**
     * Returns a stream consisting of the results of applying the given
     * function to the elements of this stream.
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @param <R> The element type of the new stream
     * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *               <a href="package-summary.html#Statelessness">stateless</a>
     *               function to apply to each element
     * @return the new stream
     */
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);  

来看Function

 @FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);  

返回R,输入一个参数。

里面搜索Integer里面的方法。

 ToLongFunction<Integer> integerToIntFunction = Integer::longValue;  

立马发现Integer里面有一个longValue符合。

最终代码如下

 List<Integer> test = new ArrayList<>();
List<Long> testLong = test.stream().map(Integer::longValue).collect(Collectors.toList());  

相信大家到了这里,一定明白了,”::”把我们的方法转化成了对应的函数式参数传递进函数里面了。

我们再来看看前面学过的Lambda表达式

 //没有输入参数 返回一个数字,所以对应Supplier<Integer>
Supplier<Integer> test = () ->5 ;

//输入两个参数,执行对应的方法 所以对应BiConsumer<Integer,Integer>
BiConsumer<Integer,Integer> test2 = (x,y) -> {};

//输入两个参数,有返回值是否相等, 所以对应BiPredicate<Integer,Integer>
BiPredicate<Integer,Integer> test3 = (x,y) -> x.equals(y);  

以后如果遇到需要使用到的”::”的地方,我们先观察函数参数是什么,需要什么参数,返回什么对象。然后找对应的处理的方法即可。

当然,Java 8 函数式接口远不止这些。

但是用起来了,让自己的代码 起来就行。

「JAVA8」- 神奇的双":"号

文章来源:智云一二三科技

文章标题:「JAVA8」- 神奇的双":"号

文章地址:https://www.zhihuclub.com/182961.shtml

关于作者: 智云科技

热门文章

网站地图