双冒号写法可以直接放进Thread()里的原因

小朋友你是否有很多问号?我是一个从汽车行业转行IT的项目经理,我是Edward。今天学volatile的时候发现了一个奇怪的现象,为什么会有对象直接双冒号接方法的写法? 为什么还可以直接放到Thread()里? 要知道没有继承Runnable接口对象的方法是不能直接放到Thread()里的哟。

先放上这段令人以后的代码:

package com.mashibing.juc.c_012_volatile;

import java.util.concurrent.TimeUnit;

/**
 * volatile关键字,使一个变量在多个线程间可见
* @author EP
* @date 2020年4月10日  
* @version 1.0
 */

public class T01_HelloVolatile {
	/*volatile*/ boolean running = true;
	void m() {
		System.out.println("m start");
		while (running) {
			
		}
		System.out.println("m end!");
	}
	
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		T01_HelloVolatile t = new T01_HelloVolatile();
		new Thread(t::m, "t1").start();
		
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t.running = false;    
		/*
		 * 不加volatile时,main线程中running属性的变化,
		 * t1线程中执行m方法中是看不见的,while会无限循环
		 */

	}

}

首先回答第一个问题,为什么会有对象后面直接双冒号接方法的写法:

这是一种eta-conversion。
支持lambda表达式的语言大多都支持eta转换,scala和 haskell 里的 eta转换写法比较简洁: x => abs(x) 经过 eta转换可以写为 abs 举个例子:scala> def hf(i:Int, f: Int=>Int) = f(i)hf: (i: Int, f: Int => Int)Intscala> hf(-99, x=>Math.abs(x))res3: Int = 99上面对高阶函数 hf 传递的第二个参数 x=>Math.abs(x) 是一段lambda表达式,这个lambda经过eta转换之后可以直接写为 Math.abs,下面是等价的写法:scala> hf(-99, Math.abs)res2: Int = 99 上面传递的第二个参数 Math.abs 看上去只是一个函数名称,实际上是一段lambda的缩写。
在java里同样也支持 eta 转换,但java对 eta转换 在风格上不同于 scala/haskell ,而是必须通过:: 来表示的,比如:number -> Math.abs(number) 经过eta转换后是 Math::abs 为什么Java要用:: 来表示eta转换,猜测可能是设计者考虑到java广大用户并不那么熟悉函数式风格,直接用一个函数名表达转换后的lambda 容易在理解上有歧义,就像上面 Math.abs 可能被新手把abs误解为Math里的一个静态常量而非方法,所以写成 Math::abs 就不容易误解了。
简单地说,就是::同样是Java语言面向函数的一个调整,属于lambda表达式的特殊写法。

那么再接下来回答第二个问题:

java 8之后,Runnable,Callable等接口都被添加了@FunctionalInterface标签。这个标签表示,这个接口是一个函数式接口,也就是该类有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,是可以用lambda表达式来表示的。所以,Thread的构造方法里,不是一定得传入Runnable对象了,而是传入函数式接口就可以。
因此,lambda的表达式就可以进一步被简写为双冒号的形式来直接引出这个方法的同时实现Runnable接口了。
举个栗子:

Runnable runnable =  () -> hellooo();
new Thread(runnable).start();

也可以这么写:

Runnable runnable =  AtomicDemo::hellooo;
new Thread(runnable).start();
原创文章 46 获赞 7 访问量 2076

猜你喜欢

转载自blog.csdn.net/EdwardWH/article/details/105431730