
Lambda,是不是聽著很熟悉,沒(méi)錯(cuò),在高等數(shù)學(xué)中這貨經(jīng)常和我們打交道,哈哈,這是一個(gè)希臘字母了,排名第十一,大寫是Λ,小寫是λ。
好了,是這樣的。jdk1.8中新增的核心特性有l(wèi)ambda表達(dá)式,函數(shù)式接口,流API,默認(rèn)方法,新的Date,以及Time API。
下面給大家介紹的是Lambda表達(dá)式,該表達(dá)式允許我們把行為傳到函數(shù)里。之前把行為傳到函數(shù)里我們采用的是匿名內(nèi)部類,該方法導(dǎo)致行為最重要的方法夾雜在中間,不夠突出。
lambda表達(dá)式取代了匿名內(nèi)部類,取消了模板,允許程序猿用函數(shù)式風(fēng)格編寫代碼,使代碼可讀性更高,盡管剛開始你會(huì)看不懂,但是你應(yīng)該嘗試,畢竟這是新的東西,我已從中獲益。
Lambda表達(dá)式是在JDK 8中開始支持的一種函數(shù)式推導(dǎo)語(yǔ)言, 能夠大量減少匿名內(nèi)部類那種冗余的代碼。 在Android中, 可以大量使用在設(shè)置監(jiān)聽, 設(shè)置異步回調(diào)等場(chǎng)景。
基本格式是:() -> {}
有下面三種具體表達(dá):
(params) -> exPRession(params) -> statement(params) -> {statement}1.引入retrolambda插件:
as里的配置 要使用lambda,首先必須配置編譯環(huán)境,這里使用的android studio,as默認(rèn)的jdk版本是1.6,修改成1.8即可使用,這里確保你系統(tǒng)安裝了jdk1.8,否則需要用到下面插件: gradle-retrolambda
一。 jdk8裝上二。在project 的build.gradle dependencies { classpath 'com.android.tools.build:gradle:2.0.0' classpath 'me.tatarka:gradle-retrolambda:3.2.5' }三。在android module 的build.gradleapply plugin: 'com.android.application'apply plugin: 'me.tatarka.retrolambda'android { //設(shè)置當(dāng)前的jdk編譯版本 8 compileOptions { sourceCompatibility javaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }設(shè)置項(xiàng)目結(jié)構(gòu) 按快捷鍵Ctrl+Shift+Alt+S進(jìn)入項(xiàng)目結(jié)構(gòu)設(shè)置,把a(bǔ)pp的jdk版本修改成1.8,注意你需要填寫1.8,因?yàn)槟莻€(gè)下拉菜單里沒(méi)有這一選項(xiàng),如下:
這里采用的是第二種方法,然后項(xiàng)目自動(dòng)同步。
同步后是會(huì)在build.gradle腳本下生成和上面一樣的東東: 
點(diǎn)擊按鈕觸發(fā)事件 傳統(tǒng)的點(diǎn)擊事件,應(yīng)用匿名內(nèi)部類:
Button button = (Button) findViewById(R.id.btn_insert); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_LONG).show(); } });通過(guò)上面設(shè)置jdk版本為1.8后,鼠標(biāo)放到new View.OnClickListener()里會(huì)有下面 然后我們按快捷鍵Alt+Enter,是這樣的
Button button = (Button) findViewById(R.id.btn_insert);button.setOnClickListener(v -> Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_LONG).show());一行代碼就搞定了,清晰可見,把行為傳到了函數(shù)里,這里注意v不可省略,是函數(shù)onClick的參數(shù),當(dāng)然就可以是任意名字,我還是建議就用一個(gè)字母表示,簡(jiǎn)單嘛,當(dāng)然了首先你得知道她的意思,盡管她的很多行為你始終不會(huì)明白
實(shí)現(xiàn)Runnable接口 傳統(tǒng)實(shí)現(xiàn)Runnable接口是這樣的:
new Thread(new Runnable() { @Override public void run() { Log.i("TAG", "haha"); }}).start();使用lambda表達(dá)式之后是這樣的:
new Thread(() -> { Log.i("TAG", "haha");}).start();
栗子
private void case2() {//2.2.按鈕點(diǎn)擊Button button = (Button) findViewById(R.id.btn);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "點(diǎn)", Toast.LENGTH_SHORT).show();}});button.setOnClickListener((View v) ->Toast.makeText(MainActivity.this, "點(diǎn)", Toast.LENGTH_SHORT).show());}1。 方法引用是什么? 是lambda表達(dá)式的一個(gè)簡(jiǎn)化寫法. 方法引用語(yǔ)法:左邊是容器( 可以是類名, 實(shí)例名) , 中間是” :: “, 右邊是相應(yīng)的方法名。 如下
一般方法的引用格式是 如果是靜態(tài)方法, 則是ClassName::methodName。 如 Object ::equals 如果是實(shí)例方法, 則是Instance::methodName。 如Object obj=new Object();obj::equals; 構(gòu)造函數(shù).則是ClassName::new
//這里setOnClickListener方法的參數(shù)是OnClickListener, 是一個(gè)函數(shù)式接口//使用lambda表達(dá)式方式button1.setOnClickListener(v -> { System.out.println("這里是Lambda實(shí)現(xiàn)方式"); });//使用方法引用方式button2.setOnClickListener(TestMethodReference::doSomething);} public static void doSomething(ActionEvent e) {System.out.println("這里是方法引用實(shí)現(xiàn)方式");}private void case3() {//2.3.雙冒號(hào):: 更簡(jiǎn)化的lambda表達(dá)式Button button = (Button) findViewById(R.id.btn);//button.setOnClickListener(Cat::toast);//調(diào)用靜態(tài)方法的例子 要求toast的參數(shù)與OnClickListner一致//Cat cat=new Cat();//button.setOnClickListener(cat::toast2);//調(diào)用成員方法的例子 要求toast2的參數(shù)與OnClickListner一致button.setOnClickListener(Cat::new);//調(diào)用構(gòu)造方法方法的例子 要求構(gòu)造方法的參數(shù)與OnClickListner一致}既然lambda表達(dá)式即將正式取代Java代碼中的匿名內(nèi)部類,那么有必要對(duì)二者做一個(gè)比較分析。
第一個(gè)關(guān)鍵的不同點(diǎn)就是關(guān)鍵字 this。匿名類的 this 關(guān)鍵字指向匿名類,而lambda表達(dá)式的 this 關(guān)鍵字指向包圍lambda表達(dá)式的類。
第二是編譯方式。Java編譯器將lambda表達(dá)式編譯成類的私有方法。使用了Java 7的 invokedynamic 字節(jié)碼指令來(lái)動(dòng)態(tài)綁定這個(gè)方法。
什么是泛型 泛型是Java SE 1.5的新特性, 通俗點(diǎn)將就是“類型的變量”。 這種類型變量可以用在類、 接口和方法的創(chuàng)建中。
List<Apple> box = new ArrayList<Apple>();box.add(new Apple());Apple apple =box.get(0);如果沒(méi)有泛型就可需要類型轉(zhuǎn)換
Apple apple = (Apple)box.get(0);什么是自動(dòng)推斷 java7的泛型類型推斷改進(jìn):為了減少泛型的代碼長(zhǎng)度。 例如: Jdk7之前
Map<String, String> myMap = new HashMap<String, String>();而使用jdk7自動(dòng)推斷之后:
Map<String, String> myMap = new HashMap<>(); //注意后面的"<>"為什么可以這樣做? 聲明變量的的時(shí)候已經(jīng)指明了參數(shù)類型, 所以就不需要在初始化對(duì)象時(shí)再指定? 看到這點(diǎn):JDK7新增了根據(jù)聲明變量獲取參數(shù)類型的這一特性就叫 自動(dòng)推斷 . Java8的泛型類型推斷改進(jìn)
//通過(guò)方法賦值的目標(biāo)參數(shù)來(lái)自動(dòng)推斷泛型的類型List<String> l = List.nil();//而不是顯示的指定類型//List<String> l = List.<String>nil();//通過(guò)前面方法參數(shù)類型推斷泛型的類型List.cons(42, List.nil());//而不是顯示的指定類型//List.cons(42, List.<Integer>nil());1。 外部VS forEach 內(nèi)部迭代 以前Java集合是不能夠表達(dá)內(nèi)部迭代的, 而只提供了一種外部迭代的方式, 也就是for或者while循環(huán)。 jdk8之前
List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John"));for (Person p : persons) {p.setLastName("Doe");}jdk8 用lambda和Collection.forEach重寫上面的循環(huán)
persons.forEach(p->p.setLastName("Doe"));新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注