深入理解Java雙冒號(::)運算子的使用

ryelqy發表於2024-03-20

Jdk8中有好多新的特性,比如引入Lambda,簡化程式碼的書寫等等

我們先看一個關於Lambda的使用

/**
* 輸出list
 */
@Test
public void test() {
    String[] array = {"aaaa", "bbbb", "cccc"};
    List<String> list = Arrays.asList(array);
    
    //Java 7 
    for(String s:list){
        System.out.println(s);
    }
    
    //Java 8
    list.forEach(System.out::println);
}

其中list.forEach(System.out::println);就是Java 8中的Lambda寫法之一, 有沒有特別注意到輸出語句跟我們平時寫的syso語句不一樣

雙冒號(::)

英文:double colon,雙冒號(::)運算子在Java 8中被用作方法引用(method reference),方法引用是與lambda表示式相關的一個重要特性。它提供了一種不執行方法的方法。為此,方法引用需要由相容的函式介面組成的目標型別上下文。

Method References
You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it’s often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.
關於方法引用的描述,摘自oracle官網

大致意思是,使用lambda表示式會建立匿名方法, 但有時候需要使用一個lambda表示式只呼叫一個已經存在的方法(不做其它), 所以這才有了方法引用!

以下是Java 8中方法引用的一些語法:

  • 靜態方法引用(static method)語法:classname::methodname 例如:Person::getAge
  • 物件的例項方法引用語法:instancename::methodname 例如:System.out::println
  • 物件的超類方法引用語法: super::methodname
  • 類構造器引用語法: classname::new 例如:ArrayList::new
  • 陣列構造器引用語法: typename[]::new 例如: String[]:new
  • 如果上的語法太枯燥,那就透過一些例子來加強對它的理解:

下面是一些例子:

靜態方法語法使用例子:

import java.util.Arrays;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * 
 * @author zhoufy
 * @date 2019年2月20日 下午2:19:13
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan("com.zhoufy")
public class Demo {
    @Test
    public void test() {
        List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
        
        //靜態方法語法    ClassName::methodName
        list.forEach(Demo::print);
    }
    
    public static void print(String content){
        System.out.println(content);
    }
}

類例項方法語法使用例子:

import java.util.Arrays;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * 
 * @author zhoufy
 * @date 2019年2月20日 下午2:19:13
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan("com.zhoufy")
public class Demo {
    @Test
    public void test() {
        List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
        
        //物件例項語法    instanceRef::methodName
        list.forEach(new Demo()::print);
    }
    
    public void print(String content){
        System.out.println(content);
    }
}

超類方法語法使用例子:

import java.util.Arrays;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


/**
 * @author zhoufy
 * @date 2019年2月20日 下午2:41:38
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan("com.zhoufy")
public class Example extends BaseExample{

    @Test
    public void test() {
        List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
        
        //物件的超類方法語法: super::methodName 
        list.forEach(super::print);
    }
}

class BaseExample {
    public void print(String content){
        System.out.println(content);
    }
}

類構造器語法使用例子:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * 
 * @author zhoufy
 * @date 2019年2月20日 下午2:19:13
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan("com.zhoufy")
public class Example {

    @Test
    public void test() {
        InterfaceExample com =  Example::new;
        Example bean = com.create();    
        System.out.println(bean);
    }
}

interface InterfaceExample{
    Example create();
}

如果是帶引數的構造器,示例如下:

/**
 * @author zhoufy
 * @date 2019年2月20日 下午2:19:13
 */
public class Example {
    
    private String name;
    
    Example(String name){
        this.name = name;
    }
    
    public static void main(String[] args) {
        InterfaceExample com =  Example::new;
        Example bean = com.create("hello world");
        System.out.println(bean.name);
    }
}
interface InterfaceExample{
    Example create(String name);
}

這裡需要特別注意的是:Example 類並沒有implements InterfaceExample介面哦!!!

陣列構造器語法使用例子:

import java.util.function.Function;

/**
 * @author zhoufy
 * @date 2019年2月20日 下午2:19:13
 */
public class Example {
    public static void main(String[] args) {
        Function <Integer, Example[]> function = Example[]::new;
        Example[] array = function.apply(4);    //這裡的4是陣列的大小
        
        for(Example e:array){
            System.out.println(e);    //如果輸出的話,你會發現會輸出4個空物件(null)
        }
    }
}

這裡是借用jdk自帶的java.util.function.Function類實現的,如果想要自定義介面

/**
 * 
 * @author zhoufy
 * @date 2019年2月20日 下午2:19:13
 */
public class Example {
    
    public static void main(String[] args) {
        Interface <Integer, Example[]> function = Example[]::new;
        Example[] array = function.apply(4);    //這裡的4是陣列的大小
        
        for(Example e:array){
            System.out.println(e);
        }
    }
}

@FunctionalInterface
interface Interface<A, T>{
    T apply(A a); 
}


————————————————

版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。

原文連結:https://blog.csdn.net/zhoufanyang_china/article/details/87798829

相關文章