1. 程式人生 > 其它 >Java學習筆記day13-內部類-Lambda表示式

Java學習筆記day13-內部類-Lambda表示式

技術標籤:筆記java

Day13

內部類

概述:
  • 內部類:就是在一個類中定義一個類。例如:在一個A類的內部定義一個B類,B類就被稱為內部類;

  • 建立格式:外部類名.內部類名 物件名 = new 外部類物件().new 內部類物件();

內部類的訪問特點
  • 內部類可以直接訪問外部類的成員,包括私有;
  • 外部類要訪問內部類的成員,必須建立物件;

按照內部類在類中的定義位置不同,可分為如下兩種:

  • 在類的成員位置:成員內部類;
  • 在類的區域性位置:區域性內部類;
成員內部類

​ 成員內部類也屬於成員,既然是成員就可以被一些修飾符所修飾

  • private
    • 私有成員內部類訪問:在自己所在的外部類中建立物件訪問。
  • static
    • 靜態成員內部類訪問格式:外部類名.內部類名 物件名 = new 外部類名.內部類名();
    • 靜態成員內部類中的靜態方法:外部類名.內部類名.方法名();
區域性內部類

​ 區域性內部類是在方法中定義的類,所以外界是無法直接使用,需要在方法內部建立物件並使用,該類可以直接訪問外部類的成員,也可以訪問方法內部的區域性變數。

package neibulei;

public class InClassTest {
    public static void main(String[] args) {
        Out o = new Out();
        o.method
(); } } class Out{ int a = 10; public void method(){ int b = 20; class Inner{ public void show(){ System.out.println(a); System.out.println(b); System.out.println("show..."); } } //通過物件呼叫show方法
Inner i = new Inner(); i.show(); } }

執行結果:
在這裡插入圖片描述
注意(在內部類的方法中呼叫外部類、內部類及內部類方法中的變數)

請問下面橫線處分別填寫什麼程式碼,才能實現打印出註釋的結果
class Outside{
		private int a = 100;
		class Inside{
			private int a = 200;
			public void show(){
				int a = 300;
				System.out.println(_Outside.this.a_);//100
				System.out.println(_Inside.this.a_);//200
				Ssytem.out.println(_a_);//300
			}
		}
	}
匿名內部類
  • 概述:匿名內部類本質上是一個特殊的區域性內部類(定義在方法內部)
  • 前提:需要存在一個介面或類
格式:
new 類名或介面名(){
	重寫方法;
}
範例:
new Inter(){
    public void show(){
        
    }
}
  • 理解:匿名內部類是將(繼承\實現)(方法重寫)(建立物件)三個步驟,放在了一步進行
匿名內部類的使用場景

​ 當方法的形式引數是介面或者抽象類時,可以將匿名內部類作為實際引數進行傳遞。

package neibulei;

public class NiMing {
    public static void main(String[] args) {
        //將匿名內部類作為實際引數進行傳遞
        useGanNailuo(new GanNailuo() {
            @Override
            public void xineilalaku() {
                System.out.println("xineilalaku!");
            }
        });
    }
    //定義一個方法,以介面為形式引數,方法內呼叫了介面的抽象方法
    public static void useGanNailuo(GanNailuo ganNailuo){
        ganNailuo.xineilalaku();
    }
}
//定義一個介面
interface GanNailuo{
    public abstract void xineilalaku();
}

Lambda表示式

函數語言程式設計思想概述
  • 在數學中,函式就是有輸入量、輸出量的一套計算方案,也就是“拿資料做操作”
  • 面向物件思想強調“必須通過物件的形式來做事情”
  • 函式式思想則儘量忽略面向物件的複雜語法:“強調做什麼,而不是以什麼形式去做”
Lambda表示式的標準格式
  • 格式:(形式引數)->{程式碼塊}
  • 形式引數:如果有多個引數,引數之間用逗號隔開;如果沒有引數留空即可
  • ->:由英文中畫線和大於符號組成,固定寫法。代表指向動作
  • 程式碼塊:是我們具體要做的事情,也就是以前我們寫的方法體內容

Lambda表示式的使用前提

  • 有一個介面
  • 介面中有且僅有一個抽象方法

案例1(無引數無返回值):

  1. 編寫一個介面(ShowHandler)
  2. 在該介面中存在一個抽象方法(show),該方法是無引數無返回值
  3. 在測試類(ShowHandlerDemo)中存在一個方法(useShowHandler),方法的引數是ShowHandler型別的,在方法內部呼叫了ShowHandler的show方法
package Lambda;

public class TestLambda {
    public static void main(String[] args) {
        useShowHandler(new ShowHandler() {
            @Override
            public void show() {
                System.out.println("我是匿名內部類中的show方法");
            }
        });
        //Lambda實現
        useShowHandler(()->{
            System.out.println("我是Lambda中的show方法");
        });
    }
    public static void useShowHandler(ShowHandler showHandler){
        showHandler.show();
    }
}
interface ShowHandler{
    void show();
}

執行結果:
在這裡插入圖片描述

案例2(帶引數無返回值)

  1. 首先存在一個介面(StringHandler)
  2. 在該介面中存在一個抽象方法(printMessage),該方法是有引數無返回值
  3. 在測試類(StringHandlerDemo)中存在一個方法(useStringHandler),方法的引數是StringHAndler型別的,在方法內部呼叫了StringHandler的printMessage方法
package Lambda;

public class StringHandlerDemo {
    public static void main(String[] args) {
        useStringHandler(new StringHandler() {
            @Override
            public void printMessage(String msg) {
                System.out.println("我是匿名內部類"+msg);
            }
        });
        //lambda實現
        useStringHandler((String msg) -> {
            System.out.println("我是Lambda表示式"+msg);
        });
    }
    public static void useStringHandler(StringHandler stringHandler){
        stringHandler.printMessage("lambda練習");
    }
}
interface StringHandler{
    void printMessage(String msg);
}

執行結果:
在這裡插入圖片描述

案例3(無引數有返回值)

  1. 首先存在一個介面(RandomNumHandler)
  2. 在該介面中存在一個抽象方法(getNumber),該方法是無引數但是有返回值
  3. 在測試類(RandomNumHandlerDemo)中存在一個方法(useRandomNumHandler),方法的引數是RandomNumHandler型別的,在方法內部呼叫了RandomNumHandler的getNumber方法
package Lambda;

import java.util.Random;

public class RandomNumHandlerDemo {
    public static void main(String[] args) {
        useRandomNumHandler(new RandomNumHandler() {
            @Override
            public int getNumber() {
                Random r = new Random();
                int a = r.nextInt(100)+1;
                return a;
            }
        });
        //Lambda實現
        useRandomNumHandler(()->{
            Random r = new Random();
            int a = r.nextInt(10)+1;
            return a;
        });
    }
    public static void useRandomNumHandler(RandomNumHandler randomNumHandler){
        int result = randomNumHandler.getNumber();
        System.out.println(result);
    }
}
interface RandomNumHandler{
    int getNumber();
}


執行結果:兩個隨機數

案例4(有引數有返回值)

  1. 首先存在一個介面(Calculator)

  2. 在該介面中存在一個抽象方法(calc),該方法是有引數也有返回值

  3. 在測試類(CalculatorDemo)中存在一個方法(useCalculator),方法的引數是Calculator型別的,在方法內部呼叫了Calculator的calc方法

package Lambda;

public class CalculatorDemo {
    public static void main(String[] args) {
        useCalculator(new Calculator() {
            @Override
            public int calc(int a, int b) {
                return a+b;
            }
        });
        //Lambda實現
        useCalculator((int a,int b)->{
            return a+b;
        });
    }
    public static void useCalculator(Calculator calculator){
        int result = calculator.calc(27,68);
        System.out.println(result);
    }
}
interface Calculator{
    int calc(int a,int b);
}


執行結果:
    95
    95
Lambda的省略模式

省略規則:

  • 引數型別可以省略,但是有多個引數的情況下,不能只省略一個
  • 如果引數有且僅有一個,那麼小括號可以省略
  • 如果程式碼塊的語句只有一條,可以省略大括號和分號,甚至是return
Lambda表示式和匿名內部類的區別

所需型別不同

  • 匿名內部類:可以是介面,也可以是抽象類,還可以是具體類
  • Lambda表示式:只能是介面

使用限制不同

  • 如果介面中有且僅有一個抽象方法,可以使用Lambda表示式,也可以使用匿名內部類
  • 如果介面中多於一個抽象方法,只能使用匿名內部類,而不能使用Lambda表示式

實現原理不同

  • 匿名內部類:編譯之後,產生一個單獨的.class位元組碼檔案
  • Lambda表示式:編譯之後,沒有一個單獨的.class位元組碼檔案。對應的位元組碼會在執行的時候動態生成

練習1

給定一個計算器Calculator介面,內含抽象方法calc (減法),其功能是可以將兩個數字進行相減,並返回差值;

請分別使用Lambda的標準格式及省略格式呼叫 invokeCalc 方法,完成130和120的相減計算並輸出計算結果;

public interface Calculator {
	int calc(int a, int b);
}
public class Test10InvokeCalc {
	public static void main(String[] args) {
		//請分別使用Lambda【標準格式】及【省略格式】呼叫invokeCalc方法來計算130-120的結果
		invokeCalc(130,120,(int a,int b)->{
            return a-b;
        });
        invokeCalc(130,120,(a,b)->a-b);
 	}

	private static void invokeCalc(int a, int b, Calculator calculator) {
		int result = calculator.calc(a, b);
  		System.out.println("結果是:" + result);
 	}
}