Java8雙冒號(::)運算符的使用

在java8中引入了很多新特性,其中最有亮點的就是函數式編程,例如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語句不一樣,常規輸出語句是這樣的:

System.out.println(“hello world!”);

這裏面使用到了::,下面接詳細介紹:

雙冒號(::)

雙冒號(::)運算符在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中方法引用的一些語法:

  1. 靜態方法引用(static method)語法:classname::methodname 例如:Person::getAge
  2. 對象的實例方法引用語法:instancename::methodname 例如:System.out::println
  3. 對象的超類方法引用語法: super::methodname
  4. 類構造器引用語法: classname::new 例如:ArrayList::new
  5. 數組構造器引用語法: 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); 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章