發(fā)布消息做任務(wù)的網(wǎng)站百度競價調(diào)價軟件
目錄
- 1、接口新特性
- 1.1 JDK8的新特性
- 1.2 JDK9的新特性
- 2、代碼塊
- 2.1 代碼塊的定義
- 2.2 代碼塊的分類
- 3、內(nèi)部類
- 3.1 內(nèi)部類的定義
- 3.2 內(nèi)部類成員訪問
- 3.3 學(xué)習(xí)內(nèi)部類的原因
- 3.4 內(nèi)部類的分類
- 3.4.1 成員內(nèi)部類
- 3.4.2 靜態(tài)內(nèi)部類
- 3.4.3 局部內(nèi)部類
- 3.4.4 匿名內(nèi)部類
- (1)定義:
- (2)使用場景:
- 4、Lambda表達(dá)式
- 4.1 概述
- 4.2 案例
- 4.3 注意事項
- 4.4 Lambda表達(dá)式的省略寫法
- 4.5 Lambda表達(dá)式和匿名內(nèi)部類的區(qū)別
- 5、窗體、組件、事件
- 5.1 窗體
- 5.2 組件
- 5.2.1 按鈕組件Jbutton
- 5.2.2 文本組件Jlabel
- 5.3 事件
- 5.4 適配器設(shè)計模式
- 5.5 模板設(shè)計模式
1、接口新特性
1.1 JDK8的新特性
之前說過,接口里面只能是抽象方法,但是JDK8為何要修改成允許定義帶方法體的方法呢,原因是什么呢?
答:如果系統(tǒng)要升級版本2,那么在接口中再新加抽象方法時,會導(dǎo)致以前的接口實現(xiàn)對象報錯,因此JDK8改成接口中可以定義有方法體的方法,就是為了解決:豐富接口功能的同時,又不需要更改實現(xiàn)類的代碼。,如下圖:
下面再看下JDK8是怎么做的:
1.2 JDK9的新特性
為什么JDK9允許定義私有方法呢?
答:
下面看看JDK9是如何做的:
2、代碼塊
2.1 代碼塊的定義
2.2 代碼塊的分類
package com.itheima.vo;public class Student {//隨著類的加載而加載,多用于數(shù)據(jù)初始化static {System.out.println("Student類的靜態(tài)代碼塊...");}//編譯時,會分散到每個構(gòu)造方法的第一行{System.out.println("Student類的構(gòu)造代碼塊...");}public Student(){//現(xiàn)在電腦內(nèi)存都很大了,所以一般不會使用局部代碼塊提前釋放內(nèi)存{System.out.println("局部代碼塊...");}System.out.println("Student類的構(gòu)造方法...");}
}
注:同步代碼塊多線程會使用到,這個放多線程介紹。
3、內(nèi)部類
3.1 內(nèi)部類的定義
下面是一個例子:
package com.itheima.inner;public class InnerTest {public static void main(String[] args) {Outer.Inner in = new Outer().new Inner();//創(chuàng)建內(nèi)部類對象in.show();//調(diào)用內(nèi)部類方法}
}class Outer{class Inner{int num = 11;public void show(){System.out.println("show...");}}
}
3.2 內(nèi)部類成員訪問
看下面這三個變量,第一個是外部類成員變量、第二個是內(nèi)部類成員變量、第三個是方法里的變量,現(xiàn)在的問題是,如何分別訪問他們?nèi)齻€?
答:看代碼
class Outer{int num = 11;//外部類成員變量class Inner{int num = 22;//內(nèi)部類成員變量public void show(){int num = 33;//方法里的變量System.out.println(num); //33System.out.println(this.num); //22System.out.println(Outer.this.num); //11}}
}
注:
1、方法里的變量:直接訪問,即就近原則;
2、內(nèi)部類成員變量:使用this
關(guān)鍵字;
3、外部類成員變量:使用外部類名稱.this
訪問。
3.3 學(xué)習(xí)內(nèi)部類的原因
3.4 內(nèi)部類的分類
3.4.1 成員內(nèi)部類
如下所示的Inner就是成員內(nèi)部類:
class Outer{class Inner{int num = 11;public void show(){System.out.println("show...");}}
}
3.4.2 靜態(tài)內(nèi)部類
注:其實可以發(fā)現(xiàn),靜態(tài)內(nèi)部類與成員內(nèi)部類主要的區(qū)別是,創(chuàng)建對象不同。記住一點:只要是靜態(tài)的,都是使用類名來調(diào)用,理解了這一點,不用刻意記也能知道靜態(tài)內(nèi)部類是怎么創(chuàng)建的。
3.4.3 局部內(nèi)部類
局部內(nèi)部類是指:放在方法、代碼塊、構(gòu)造器等執(zhí)行體中的類。
下面是一個例子:
class A{public void show(){//B是一個局部內(nèi)部類class B{int num;}}
}
局部內(nèi)部類只有在調(diào)用此代碼塊時才會調(diào)用到,因此雞肋,使用較少。
3.4.4 匿名內(nèi)部類
(1)定義:
注:
- new 類名(){}:代表繼承這個類
- new 接口名(){}:代表實現(xiàn)這個類
(2)使用場景:
如果發(fā)現(xiàn)在調(diào)用一個方法時,此方法的參數(shù)是一個接口類型,那么有兩種辦法解決:
1、定義一個此接口的實現(xiàn)類并重寫此方法,然后new這個實現(xiàn)類,最后調(diào)用這個方法;
2、使用匿名內(nèi)部類,即new 接口名(){}。
看下面的例子:
可以發(fā)現(xiàn)第二種方法很簡潔,因此這就是匿名內(nèi)部類的使用場景。
對于上述的兩種方法,要如何選擇呢?
答:如果一個接口的抽象方法很少,則推薦使用匿名內(nèi)部類,反之使用定義接口實現(xiàn)類的這種方法比較簡潔。
4、Lambda表達(dá)式
4.1 概述
4.2 案例
public class InnerTest {public static void main(String[] args) {//這是匿名內(nèi)部類useInnerA(new InnerA() {@Overridepublic void show() {System.out.println("我是匿名內(nèi)部類...");}});//使用Lambda表達(dá)式,簡化匿名內(nèi)部類useInnerA(()->{System.out.println("我是使用Lambda表達(dá)式的匿名內(nèi)部類...");});}//這是一個形參類型為接口的方法public static void useInnerA(InnerA a){a.show();}
}interface InnerA{void show();
}
4.3 注意事項
總結(jié):Lambda表達(dá)式只能簡化只有一個抽象方法的匿名內(nèi)部類。
4.4 Lambda表達(dá)式的省略寫法
下面我們一條一來看:
- 參數(shù)類型可以省略不寫:
//使用Lambda表達(dá)式,參數(shù)類型可以省略
useInnerA((a, b) -> {System.out.println("我是使用Lambda表達(dá)式的匿名內(nèi)部類...");});
- 只有一個參數(shù),則參數(shù)類型可以省略不寫,同時()也可以省略
//使用Lambda表達(dá)式,只有一個參數(shù),則參數(shù)類型可以省略不寫,同時()也可以省略
useInnerA(a -> {System.out.println("只有一個參數(shù),則參數(shù)類型可以省略不寫,同時()也可以省略...");});
- Lambda表達(dá)式的方法體只有一行代碼,大括號和分號都可省略,同時如果是return則必須省略。
//Lambda表達(dá)式的方法體只有一行代碼,大括號和分號都可省略,同時如果是return則必須省略。
//返回值為字符串類型,只需要寫字符串即可,需要省略return語句。
useInnerA(a-> "我是使用Lambda表達(dá)式的匿名內(nèi)部類...");
4.5 Lambda表達(dá)式和匿名內(nèi)部類的區(qū)別
5、窗體、組件、事件
5.1 窗體
import javax.swing.*;public class JFrameTest {public static void main(String[] args) {//創(chuàng)建窗體對象JFrame jf = new JFrame();//設(shè)置窗體大小jf.setSize(511, 511);//修改窗體的關(guān)閉模式jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置窗體標(biāo)題jf.setTitle("大哥的第一個窗口");//設(shè)置窗體可見jf.setVisible(true);}
}
5.2 組件
5.2.1 按鈕組件Jbutton
看下面代碼:
package com.itheima.frame;import javax.swing.*;public class JFrameTest {public static void main(String[] args) {//1、窗體對象//創(chuàng)建窗體對象JFrame jf = new JFrame();//設(shè)置窗體大小jf.setSize(511, 511);//修改窗體的關(guān)閉模式jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置窗體標(biāo)題jf.setTitle("我是標(biāo)題");//取消窗體的默認(rèn)布局jf.setLayout(null);//2、按鈕對象//2.1 創(chuàng)建按鈕對象JButton jb = new JButton("確定");jb.setBounds(51,51,111,111);//2.2 將按鈕對象添加到面板對象當(dāng)中jf.getContentPane().add(jb);//設(shè)置窗體可見jf.setVisible(true);}
}
5.2.2 文本組件Jlabel
5.3 事件
- 動作監(jiān)聽:
package com.itheima.action;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;public class ActionTest {public static void main(String[] args) {//1、窗體對象//創(chuàng)建窗體對象JFrame jf = new JFrame();//設(shè)置窗體大小jf.setSize(511, 511);//修改窗體的關(guān)閉模式jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置窗體標(biāo)題jf.setTitle("我是標(biāo)題");//取消窗體的默認(rèn)布局jf.setLayout(null);//2、按鈕對象//2.1 創(chuàng)建按鈕對象JButton jb = new JButton("確定");jb.setBounds(51,51,111,111);//2.2 將按鈕對象添加到面板對象當(dāng)中jf.getContentPane().add(jb);//3、事件監(jiān)聽jb.addActionListener(new AbstractAction() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("我被點擊了");}});//設(shè)置窗體可見jf.setVisible(true);}
}
- 鍵盤事件:
package com.itheima.action;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;public class KeyActionTest {public static void main(String[] args) {//1、窗體對象//創(chuàng)建窗體對象JFrame jf = new JFrame();//設(shè)置窗體大小jf.setSize(511, 511);//修改窗體的關(guān)閉模式jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置窗體標(biāo)題jf.setTitle("我是標(biāo)題");//取消窗體的默認(rèn)布局jf.setLayout(null);//鍵盤事件jf.addKeyListener(new KeyListener() {@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {//鍵盤按下時觸發(fā)事件int keyCode = e.getKeyCode();if (keyCode == 37){System.out.println("左移動業(yè)務(wù)...");} else if (keyCode == 38) {System.out.println("上移動業(yè)務(wù)...");} else if (keyCode == 39) {System.out.println("右移動業(yè)務(wù)...");} else if (keyCode == 40) {System.out.println("下移動業(yè)務(wù)...");}}@Overridepublic void keyReleased(KeyEvent e) {//鍵盤松開時觸發(fā)事件
// System.out.println("鍵盤松開了...");}});//設(shè)置窗體可見jf.setVisible(true);}
}
5.4 適配器設(shè)計模式
上述對適配器設(shè)計模式的描述可能不夠清晰,下面再用大白話解釋一下:
當(dāng)我們寫了一個接口后,我們會將這個接口進(jìn)行實現(xiàn)。在進(jìn)行一個實現(xiàn)時,我們發(fā)現(xiàn)無論怎么樣,這個實現(xiàn)類是一定要重寫接口里的所有方法的,那有什么方法只重寫想要的方法呢,這個就是適配器要解決的問題。
- 解決思路:
先編寫一個適配器(抽象方法),讓適配器來實現(xiàn)這個接口,然后我們要寫的實現(xiàn)類只需要繼承適配器就可以了,這樣我們需要實現(xiàn)哪個方法就重寫哪個即可。
如下所示::
- 解決步驟:
5.5 模板設(shè)計模式
上面的陳述可能還不是太清晰,下面再通俗的解釋一下:
模板設(shè)計模式,其實就是先寫一個抽象類,然后在抽象類里寫一個模板方法,依次調(diào)用業(yè)務(wù)邏輯代碼,但是發(fā)現(xiàn)有些業(yè)務(wù)邏輯代碼并不通用,于是把這些不通用的代碼抽為一個或者幾個方法,然后將這幾個方法定義為抽象方法,讓子類去實現(xiàn),這樣子類就會有各自的業(yè)務(wù)邏輯,這個就是模板設(shè)計模式。
下面看一段代碼:
package com.itheima.design.template;public abstract class CompositionTemplate {/*** write方法是模板,但是里面的body是隨著每個實現(xiàn)類的不同而不同,因此需要定義為抽象方法*/public void write(){System.out.println("我的爸爸");body();System.out.println("啊~ 這就是我的爸爸~");}abstract void body();
}public class Tom extends CompositionTemplate{@Overridevoid body() {System.out.println("我的爸爸是一個很嚴(yán)肅的人,每天工作很長時間。。。");}
}public class Test {public static void main(String[] args) {Tom t = new Tom();t.write();}
}輸出:我的爸爸
我的爸爸是一個很嚴(yán)肅的人,每天工作很長時間。。。
啊~ 這就是我的爸爸~Process finished with exit code 0
注意:上述代碼中,要是子類重寫了write方法,那豈不是不遵循當(dāng)初定義的模板了?為了防止重寫write方法,可以把write方法定義為最終的,即前面加關(guān)鍵字
final
,如下所示:
public abstract class CompositionTemplate {/*** write方法是模板,但是里面的body是隨著每個實現(xiàn)類的不同而不同,因此需要定義為抽象方法*/public final void write(){//定義為最終的,防止重寫System.out.println("我的爸爸");body();System.out.println("啊~ 這就是我的爸爸~");}abstract void body();
}
但其實業(yè)務(wù)代碼中一般不會這么寫死,因為萬一你寫的模板確實不適合人家的業(yè)務(wù)需求呢,那豈不是壞大事了。