Java學習筆記day13-內部類-Lambda表示式
阿新 • • 發佈:2020-12-20
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(無引數無返回值):
- 編寫一個介面(ShowHandler)
- 在該介面中存在一個抽象方法(show),該方法是無引數無返回值
- 在測試類(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(帶引數無返回值)
- 首先存在一個介面(StringHandler)
- 在該介面中存在一個抽象方法(printMessage),該方法是有引數無返回值
- 在測試類(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(無引數有返回值)
- 首先存在一個介面(RandomNumHandler)
- 在該介面中存在一個抽象方法(getNumber),該方法是無引數但是有返回值
- 在測試類(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(有引數有返回值)
-
首先存在一個介面(Calculator)
-
在該介面中存在一個抽象方法(calc),該方法是有引數也有返回值
-
在測試類(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);
}
}