定時(shí)器
定時(shí)器:可以讓我們在指定的時(shí)間做某件事情涕烧,還可以重復(fù)的做某件事情裳涛。
依賴Timer和TimerTask這兩個(gè)類:
Timer:定時(shí)
public Timer() 創(chuàng)建一個(gè)定時(shí)器對象
public void schedule(TimerTask task,long delay) 在delay延時(shí)后執(zhí)行task任務(wù)
public void schedule(TimerTask task,long delay,long period) 任務(wù)task在delay延時(shí)后開始執(zhí)行扇丛,隔period時(shí)間后再次執(zhí)行
public void cancel() 結(jié)束任務(wù)
TimerTask:任務(wù)
public class TimerDemo {
public static void main(String[] args) {
// 創(chuàng)建定時(shí)器對象
Timer t = new Timer();
// 3秒后執(zhí)行爆炸任務(wù)
// t.schedule(new MyTask(), 3000);
//結(jié)束任務(wù)
t.schedule(new MyTask(t), 3000);
}
}
// 做一個(gè)任務(wù)
class MyTask extends TimerTask {
private Timer t;
public MyTask(){}
public MyTask(Timer t){
this.t = t;
}
@Override
public void run() {
System.out.println("beng,爆炸了");
t.cancel();
}
}
public class TimerDemo2 {
public static void main(String[] args) {
// 創(chuàng)建定時(shí)器對象
Timer t = new Timer();
// 3秒后執(zhí)行爆炸任務(wù)第一次巢寡,如果不成功风纠,每隔2秒再繼續(xù)炸
t.schedule(new MyTask2(), 3000, 2000);
}
}
// 做一個(gè)任務(wù)
class MyTask2 extends TimerTask {
@Override
public void run() {
System.out.println("beng,爆炸了");
}
}
/*
* 需求:在指定的時(shí)間刪除我們的指定目錄
*/
class DeleteFolder extends TimerTask {
@Override
public void run() {
File srcFolder = new File("demo");
deleteFolder(srcFolder);
}
// 遞歸刪除目錄
public void deleteFolder(File srcFolder) {
File[] fileArray = srcFolder.listFiles();
if (fileArray != null) {
for (File file : fileArray) {
if (file.isDirectory()) {
deleteFolder(file);
} else {
System.out.println(file.getName() + ":" + file.delete());
}
}
System.out.println(srcFolder.getName() + ":" + srcFolder.delete());
}
}
}
public class TimerTest {
public static void main(String[] args) throws ParseException {
Timer t = new Timer();
String s = "2022-04-03 15:45:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
t.schedule(new DeleteFolder(), d);
}
}
1:多線程有幾種實(shí)現(xiàn)方案淆院,分別是哪幾種?
兩種。
繼承Thread類
實(shí)現(xiàn)Runnable接口
擴(kuò)展一種:實(shí)現(xiàn)Callable接口昔搂。這個(gè)得和線程池結(jié)合劳吠。
2:同步有幾種方式,分別是什么?
兩種巩趁。
同步代碼塊
同步方法
3:啟動(dòng)一個(gè)線程是run()還是start()?它們的區(qū)別?
start();
run():封裝了被線程執(zhí)行的代碼,直接調(diào)用僅僅是普通方法的調(diào)用
start():啟動(dòng)線程痒玩,并由JVM自動(dòng)調(diào)用run()方法
4:sleep()和wait()方法的區(qū)別
sleep():必須指時(shí)間;不釋放鎖
wait():可以不指定時(shí)間,也可以指定時(shí)間;釋放鎖
5:為什么wait(),notify(),notifyAll()等方法都定義在Object類中
因?yàn)檫@些方法的調(diào)用是依賴于鎖對象的议慰,而同步代碼塊的鎖對象是任意鎖蠢古。
而Object代碼任意的對象,所以别凹,定義在這里面
面向?qū)ο笏枷朐O(shè)計(jì)原則及常見的設(shè)計(jì)模式
面向?qū)ο笤O(shè)計(jì)思想原則
單一職責(zé)原則
其實(shí)就是開發(fā)人員經(jīng)常說的”高內(nèi)聚草讶,低耦合”
也就是說,每個(gè)類應(yīng)該只有一個(gè)職責(zé)炉菲,對外只能提供一種功能堕战,而引起類變化的原因應(yīng)該只有一個(gè)。在設(shè)計(jì)模式中拍霜,所有的設(shè)計(jì)模式都遵循這一原則
開閉原則
核心思想是:一個(gè)對象對擴(kuò)展開放嘱丢,對修改關(guān)閉。
其實(shí)開閉原則的意思就是:對類的改動(dòng)是通過增加代碼進(jìn)行的祠饺,而不是修改現(xiàn)有代碼越驻。
也就是說軟件開發(fā)人員一旦寫出了可以運(yùn)行的代碼,就不應(yīng)該去改動(dòng)它,而是要保證它能一直運(yùn)行下去缀旁,如何能夠做到這一點(diǎn)呢?這就需要借助于抽象和多態(tài)记劈,即把可能變化的內(nèi)容抽象出來,從而使抽象的部分是相對穩(wěn)定的并巍,而具體的實(shí)現(xiàn)則是可以改變和擴(kuò)展的目木。
里氏替換原則
核心思想:在任何父類出現(xiàn)的地方都可以用它的子類來替代。
其實(shí)就是說:同一個(gè)繼承體系中的對象應(yīng)該有共同的行為特征懊渡。
依賴注入原則
核心思想:要依賴于抽象刽射,不要依賴于具體實(shí)現(xiàn)。
其實(shí)就是說:在應(yīng)用程序中距贷,所有的類如果使用或依賴于其他的類柄冲,則應(yīng)該依賴這些其他類的抽象類吻谋,而不是這些其他類的具體類忠蝗。為了實(shí)現(xiàn)這一原則,就要求我們在編程的時(shí)候針對抽象類或者接口編程漓拾,而不是針對具體實(shí)現(xiàn)編程阁最。
接口分離原則
核心思想:不應(yīng)該強(qiáng)迫程序依賴它們不需要使用的方法。
其實(shí)就是說:一個(gè)接口不需要提供太多的行為骇两,一個(gè)接口應(yīng)該只提供一種對外的功能速种,不應(yīng)該把所有的操作都封裝到一個(gè)接口中。
迪米特原則
核心思想:一個(gè)對象應(yīng)當(dāng)對其他對象盡可能少的了解
其實(shí)就是說:降低各個(gè)對象之間的耦合低千,提高系統(tǒng)的可維護(hù)性配阵。在模塊之間應(yīng)該只通過接口編程,而不理會模塊的內(nèi)部工作原理示血,它可以使各個(gè)模塊耦合度降到最低棋傍,促進(jìn)軟件的復(fù)用
設(shè)計(jì)模式
設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的难审、經(jīng)過分類編目的瘫拣、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼告喊、讓代碼更容易被他人理解麸拄、保證代碼可靠性。
設(shè)計(jì)模式不是一種方法和技術(shù)黔姜,而是一種思想
設(shè)計(jì)模式和具體的語言無關(guān)拢切,學(xué)習(xí)設(shè)計(jì)模式就是要建立面向?qū)ο蟮乃枷耄M可能的面向接口編程秆吵,低耦合失球,高內(nèi)聚,使設(shè)計(jì)的程序可復(fù)用
學(xué)習(xí)設(shè)計(jì)模式能夠促進(jìn)對面向?qū)ο笏枷氲睦斫猓粗嗳皇蛋K鼈兿噍o相成
設(shè)計(jì)模式的幾個(gè)要素
名字 必須有一個(gè)簡單豺撑,有意義的名字
問題 描述在何時(shí)使用模式
解決方案 描述設(shè)計(jì)的組成部分以及如何解決問題
效果 描述模式的效果以及優(yōu)缺點(diǎn)
設(shè)計(jì)模式的分類
創(chuàng)建型模式 對象的創(chuàng)建
結(jié)構(gòu)型模式 對象的組成(結(jié)構(gòu))
行為型模式 對象的行為
創(chuàng)建型模式:簡單工廠模式,工廠方法模式黔牵,抽象工廠模式聪轿,建造者模式,原型模式猾浦,單例模式陆错。(6個(gè))
結(jié)構(gòu)型模式:外觀模式、適配器模式金赦、代理模式音瓷、裝飾模式、橋接模式夹抗、組合模式绳慎、享元模式。(7個(gè))
行為型模式:模版方法模式漠烧、觀察者模式杏愤、狀態(tài)模式、職責(zé)鏈模式已脓、命令模式珊楼、訪問者模式、策略模式度液、備忘錄模式厕宗、迭代器模式、解釋器模式堕担。(10個(gè))
簡單工廠模式概述
又叫靜態(tài)工廠方法模式已慢,它定義一個(gè)具體的工廠類負(fù)責(zé)創(chuàng)建一些類的實(shí)例
優(yōu)點(diǎn)
客戶端不需要在負(fù)責(zé)對象的創(chuàng)建,從而明確了各個(gè)類的職責(zé)
缺點(diǎn)
這個(gè)靜態(tài)工廠類負(fù)責(zé)所有對象的創(chuàng)建照宝,如果有新的對象增加蛇受,或者某些對象的創(chuàng)建方式不同,就需要不斷的修改工廠類厕鹃,不利于后期的維護(hù)
//動(dòng)物類
public abstract class Animal {
public abstract void eat();
}
//動(dòng)物工廠類
public class AnimalFactory {
private AnimalFactory() {
}
// public static Dog createDog() {
// return new Dog();
// }
//
// public static Cat createCat() {
// return new Cat();
// }
public static Animal createAnimal(String type) {
if ("dog".equals(type)) {
return new Dog();
} else if ("cat".equals(type)) {
return new Cat();
} else {
return null;
}
}
}
//測試類
public class AnimalDemo {
public static void main(String[] args) {
// 具體類調(diào)用沒寫
Dog d = new Dog();
d.eat();
Cat c = new Cat();
c.eat();
System.out.println("------------");
// 工廠有了后兢仰,通過工廠給造
// Dog dd = AnimalFactory.createDog();
// Cat cc = AnimalFactory.createCat();
// dd.eat();
// cc.eat();
// System.out.println("------------");
// 工廠改進(jìn)后
Animal a = AnimalFactory.createAnimal("dog");
a.eat();
a = AnimalFactory.createAnimal("cat");
a.eat();
// NullPointerException
a = AnimalFactory.createAnimal("pig");
if (a != null) {
a.eat();
} else {
System.out.println("對不起,暫時(shí)不提供這種動(dòng)物");
}
}
}
工廠方法模式概述
工廠方法模式中抽象工廠類負(fù)責(zé)定義創(chuàng)建對象的接口剂碴,具體對象的創(chuàng)建工作由繼承抽象工廠的具體類實(shí)現(xiàn)把将。
優(yōu)點(diǎn)
客戶端不需要在負(fù)責(zé)對象的創(chuàng)建,從而明確了各個(gè)類的職責(zé)忆矛,如果有新的對象增加察蹲,只需要增加一個(gè)具體的類和具體的工廠類即可请垛,不影響已有的代碼,后期維護(hù)容易洽议,增強(qiáng)了系統(tǒng)的擴(kuò)展性
缺點(diǎn)
需要額外的編寫代碼宗收,增加了工作量
public abstract class Animal {
public abstract void eat();
}
public class DogFactory implements Factory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
public class DogFactory implements Factory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
public class CatFactory implements Factory {
@Override
public Animal createAnimal() {
return new Cat();
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("貓吃魚");
}
}
public class AnimalDemo {
public static void main(String[] args) {
// 需求:我要狗
Factory f = new DogFactory();
Animal a = f.createAnimal();
a.eat();
System.out.println("-------");
//需求:我要貓
f = new CatFactory();
a = f.createAnimal();
a.eat();
}
}
單例設(shè)計(jì)模式概述
單例模式就是要確保類在內(nèi)存中只有一個(gè)對象,該實(shí)例必須自動(dòng)創(chuàng)建亚兄,并且對外提供混稽。
優(yōu)點(diǎn)
在系統(tǒng)內(nèi)存中只存在一個(gè)對象,因此可以節(jié)約系統(tǒng)資源审胚,對于一些需要頻繁創(chuàng)建和銷毀的對象單例模式無疑可以提高系統(tǒng)的性能匈勋。
缺點(diǎn)
沒有抽象層,因此擴(kuò)展很難膳叨。
職責(zé)過重洽洁,在一定程序上違背了單一職責(zé)
單例模式餓漢式類,類一加載就創(chuàng)建菲嘴,保證類在內(nèi)存中只有一個(gè)對象
如何保證類在內(nèi)存中只有一個(gè)對象
把構(gòu)造方法私有
在成員位置自己創(chuàng)建一個(gè)對象
通過一個(gè)公共的方法提供訪問
public class Student {
// 構(gòu)造私有
private Student() {
}
// 自己造一個(gè)
// 靜態(tài)方法只能訪問靜態(tài)成員變量饿自,加靜態(tài)
// 為了不讓外界直接訪問修改這個(gè)值,加private
private static Student s = new Student();
// 提供公共的訪問方式
// 為了保證外界能夠直接使用該方法临谱,加靜態(tài)
public static Student getStudent() {
return s;
}
}
public class StudentDemo {
public static void main(String[] args) {
// Student s1 = new Student();
// Student s2 = new Student();
// System.out.println(s1 == s2); // false
// 通過單例如何得到對象呢?
// Student.s = null;
Student s1 = Student.getStudent();
Student s2 = Student.getStudent();
System.out.println(s1 == s2);
System.out.println(s1); // null璃俗,cn.itcast_03.Student@175078b
System.out.println(s2);// null奴璃,cn.itcast_03.Student@175078b
}
}
單例模式懶漢式悉默,用的時(shí)候,才去創(chuàng)建對象
面試題:單例模式的思想是什么?請寫一個(gè)代碼體現(xiàn)苟穆。
開發(fā):餓漢式(是不會出問題的單例模式)
面試:懶漢式(可能會出問題的單例模式)
懶加載(延遲加載)
線程安全問題
是否多線程環(huán)境 是
是否有共享數(shù)據(jù) 是
是否有多條語句操作共享數(shù)據(jù) 是
public class Teacher {
private Teacher() {
}
private static Teacher t = null;
public synchronized static Teacher getTeacher() {
// t1,t2,t3
if (t == null) {
//t1,t2,t3
t = new Teacher();
}
return t;
}
}
public class TeacherDemo {
public static void main(String[] args) {
Teacher t1 = Teacher.getTeacher();
Teacher t2 = Teacher.getTeacher();
System.out.println(t1 == t2);
System.out.println(t1); // cn.itcast_03.Teacher@175078b
System.out.println(t2);// cn.itcast_03.Teacher@175078b
}
}
Day25
GUI
Graphical User Interface(圖形用戶接口)
用圖形的方式抄课,來顯示計(jì)算機(jī)操作的界面,這樣更方便更直觀
方法
構(gòu)造方法
Frame():創(chuàng)建一個(gè)不可見的窗體
Frame f = new Frame();
Frame(String title):創(chuàng)建一個(gè)帶標(biāo)題的不可見窗體
Frame f = new Frame(Hello,世界);
設(shè)置窗口可見
f.show();//已過時(shí)
f.setVisible(true);//true代表可見雳旅,false代表不可見
設(shè)置窗體標(biāo)題
f.setTitle("HelloWorld");
等同于帶參構(gòu)造跟磨,同時(shí)出現(xiàn)時(shí)會更改帶參構(gòu)造的標(biāo)題名
設(shè)置窗體大小
直接設(shè)置:f.setSize(400, 300); //單位:像素
借助Dimension類:Dimension(int width, int height)
Dimension d = new Dimension(400, 300); f.setSize(d);
設(shè)置窗體位置
直接設(shè)置:f.setLocation(400, 200);//單位:像素
借助Point類:Point(int x, int y)
Point p = new Point(400, 200); f.setLocation(p);
一個(gè)方法設(shè)置窗體大小和位置
f.setBounds(x,y,width,height);
f.setBounds(400,200,400,300);
事件監(jiān)聽機(jī)制
事件源 事件發(fā)生的地方
事件 就是要發(fā)生的事情
事件處理 就是針對發(fā)生的事情做出的處理方案
事件監(jiān)聽 就是把事件源和事件關(guān)聯(lián)起來
舉例:人受傷事件
事件源:人(具體的對象)
Person p1 = new Person("張三");
Person p2 = new Person("李四");
事件:受傷
interface 受傷接口 {
一拳();
一板磚();
}
事件處理:
受傷處理類 implements 受傷接口 {
一拳(){ System.out.println("鼻子流血了,送到衛(wèi)生間洗洗"); }
一板磚(){ System.out.println("頭破血流攒盈,送到太平間"); }
}
事件監(jiān)聽:
p1.注冊監(jiān)聽(受傷接口)
關(guān)閉窗口
f.addWindowListener(new WindowListener(){重寫這個(gè)匿名內(nèi)部類的所有方法抵拘,(可以空實(shí)現(xiàn)),將windowClosing(WindowEvent e) 方法為System.exit(0);});
適配器改進(jìn)
f.addWindowListener(new WindowAdapter() { 重寫這個(gè)適配器類的windowClosing方法為System.exit(0);});
創(chuàng)建按鈕
Button bu = new Button();
創(chuàng)建并設(shè)置名字
Button bu = new Button("按鈕");
把按鈕添加到窗體
f.add(bu);
f.add();可以添加任意組件型豁,按鈕僵蛛,文本框,文本域等
** 設(shè)置布局為流式布局**
f.setLayout(new FlowLayout());
對按鈕添加事件
bu.addActionListener(new ActionListener() {重寫actionPerformed方法});
創(chuàng)建文本框
TextField tf = new TextField();
默認(rèn)
帶一個(gè)int數(shù)值表示文本框可以放多少個(gè)字符
帶一個(gè)String的字符串迎变,就是默認(rèn)出來的字符串
帶一個(gè)String和int數(shù)值充尉,表示默認(rèn)字符串以及可以放多少個(gè)字符
創(chuàng)建文本域
TextArea ta = new TextArea();
帶兩個(gè)Int數(shù)值表示多少行多少列
獲取文本框的值
String tf_str = tf.getText().trim(); trim()時(shí)不允許有空格
設(shè)置文本框的值
tf.setText("");
為空是清空文本框
設(shè)置文本域的值
ta.setText(tf_str);
追加設(shè)置文本域的值
ta.append(tf_str + "\r\n"); \r\n表示換行
獲取光標(biāo)
tf.requestFocus();
表示將光標(biāo)的值給調(diào)用者tf
設(shè)置背景色
f.setBackground(Color.RED);
Color.可選很多顏色
鼠標(biāo)事件
void mouseClicked(MouseEvent e) 單擊并釋放
mouseEntered(MouseEvent e) 進(jìn)入
mouseExited(MouseEvent e) 離開
void mousePressed(MouseEvent e)鼠標(biāo)按鍵在組件上按下時(shí)調(diào)用
void mouseReleased(MouseEvent e)鼠標(biāo)按鈕在組件上釋放時(shí)調(diào)用
對按鈕添加鼠標(biāo)事件
Button redbutton = new Button("紅色");
redbutton.addMouseListener(new MouseAdapter() {重寫鼠標(biāo)事件的方法 });
創(chuàng)建標(biāo)簽對象
Label label = new Label("可以輸入文字");
鍵盤事件
keyPressed(KeyEvent e) 摁下某個(gè)鍵時(shí)調(diào)用
keyReleased(KeyEvent e) 釋放某個(gè)鍵時(shí)調(diào)用此方法
keyTyped(KeyEvent e) 鍵入某個(gè)鍵時(shí)調(diào)用此方法
獲取每次鍵入的值
方法:char getKeyChar()
舉例:char ch = e.getKeyChar();
取消鍵盤事件
e.consume();
菜單
創(chuàng)建菜單欄
MenuBar mb = new MenuBar();
創(chuàng)建菜單
Menu m = new Menu("文件");
創(chuàng)建菜單項(xiàng)
MenuItem mi = new MenuItem("退出系統(tǒng)");
先創(chuàng)建菜單欄,在創(chuàng)建菜單衣形,最后才是菜單項(xiàng)驼侠,菜單中可以添加菜單,作為子菜單
注意添加的順序,從小到大依次添加
將菜單欄添加到窗體(為窗體設(shè)置菜單欄)
f.setMenuBar(mb);
對菜單項(xiàng)添加事件
mi.addActionListener(new ActionListener() {重寫actionPerformed方法倒源,實(shí)現(xiàn)點(diǎn)擊時(shí)執(zhí)行相應(yīng)的功能});
Day26
網(wǎng)絡(luò)編程三要素
IP地址
端口
協(xié)議
端口號:正在運(yùn)行的程序的標(biāo)識,有效端口:065535苛预,其中01024系統(tǒng)使用或保留端口
協(xié)議:通信的規(guī)則
UDP:
把數(shù)據(jù)打包
數(shù)據(jù)有限制(64k)
不建立連接
速度快
不可靠
TCP:
建立連接通道
數(shù)據(jù)無限制
速度慢
可靠
InetAddress
public static InetAddress getByName(String host):根據(jù)主機(jī)名或者IP地址的字符串表示得到IP地址對象
public String getHostName()獲取主機(jī)名
public String getHostAddress()獲取IP地址
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// public static InetAddress getByName(String host)
// InetAddress address = InetAddress.getByName("zhangsan");
// InetAddress address = InetAddress.getByName("192.168.12.92");
InetAddress address = InetAddress.getByName("192.168.12.63");
// 獲取兩個(gè)東西:主機(jī)名,IP地址
// public String getHostName()
String name = address.getHostName();
// public String getHostAddress()
String ip = address.getHostAddress();
System.out.println(name + "---" + ip);
}
}
Socket
網(wǎng)絡(luò)套接字笋熬,網(wǎng)絡(luò)編程碟渺,套接字編程
Socket包含IP地址和端口號
Socket原理機(jī)制
通信的兩端都有Socket
網(wǎng)絡(luò)通信就是Socket之間的通信
數(shù)據(jù)在兩個(gè)Socket之間用IO流傳輸
UDP協(xié)議發(fā)送數(shù)據(jù):
創(chuàng)建發(fā)送端Socket對象(DatagramSocket無參構(gòu)造)
創(chuàng)建數(shù)據(jù),并把數(shù)據(jù)打包(DatagramPacket(byte[] buf, int length, InetAddress address, int port))數(shù)據(jù)突诬,長度苫拍,IP地址,端口號
調(diào)用Socket對象的發(fā)送方法發(fā)送數(shù)據(jù)包
釋放資源(底層為IO流傳輸)
UDP協(xié)議接收數(shù)據(jù):
創(chuàng)建接收端Socket對象(DatagramSocket(int port)指定接受的端口號)
創(chuàng)建一個(gè)數(shù)據(jù)包(接收容器DatagramPacket(byte[] buf, int length)只需要存儲的地方和長度)
調(diào)用Socket對象的接收方法接收數(shù)據(jù)(public void receive(DatagramPacket p)接收數(shù)據(jù))
解析數(shù)據(jù)包旺隙,并顯示在控制臺
釋放資源
public byte[] getData():獲取數(shù)據(jù)緩沖區(qū)
public int getLength():獲取數(shù)據(jù)的實(shí)際長度
//發(fā)送
public class SendDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建發(fā)送端Socket對象
// DatagramSocket()
DatagramSocket ds = new DatagramSocket();
// 創(chuàng)建數(shù)據(jù)绒极,并把數(shù)據(jù)打包
// DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// 創(chuàng)建數(shù)據(jù)
byte[] bys = "hello,udp,我來了".getBytes();
// 長度
int length = bys.length;
// IP地址對象
InetAddress address = InetAddress.getByName("192.168.12.92");
// 端口
int port = 10086;
DatagramPacket dp = new DatagramPacket(bys, length, address, port);
// 調(diào)用Socket對象的發(fā)送方法發(fā)送數(shù)據(jù)包
// public void send(DatagramPacket p)
ds.send(dp);
// 釋放資源
ds.close();
}
}
//接受
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建接收端Socket對象
// DatagramSocket(int port)
DatagramSocket ds = new DatagramSocket(10086);
// 創(chuàng)建一個(gè)數(shù)據(jù)包(接收容器)
// DatagramPacket(byte[] buf, int length)
byte[] bys = new byte[1024];
int length = bys.length;
DatagramPacket dp = new DatagramPacket(bys, length);
// 調(diào)用Socket對象的接收方法接收數(shù)據(jù)
// public void receive(DatagramPacket p)
ds.receive(dp); // 阻塞式
// 解析數(shù)據(jù)包,并顯示在控制臺
// 獲取對方的ip
// public InetAddress getAddress()
InetAddress address = dp.getAddress();
String ip = address.getHostAddress();
// public byte[] getData():獲取數(shù)據(jù)緩沖區(qū)
// public int getLength():獲取數(shù)據(jù)的實(shí)際長度
byte[] bys2 = dp.getData();
int len = dp.getLength();
String s = new String(bys2, 0, len);
System.out.println(ip + "傳遞的數(shù)據(jù)是:" + s);
// 釋放資源
ds.close();
}
}
對上列代碼進(jìn)行優(yōu)化
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建接收端的Socket對象
DatagramSocket ds = new DatagramSocket(12345);
// 創(chuàng)建一個(gè)包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
// 接收數(shù)據(jù)
ds.receive(dp);
// 解析數(shù)據(jù)
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
// 釋放資源
ds.close();
}
}
public class SendDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建發(fā)送端的Socket對象
DatagramSocket ds = new DatagramSocket();
// 創(chuàng)建數(shù)據(jù)并打包
byte[] bys = "helloworld".getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("192.168.12.92"), 12345);
// 發(fā)送數(shù)據(jù)
ds.send(dp);
// 釋放資源
ds.close();
}
}
鍵盤錄入數(shù)據(jù)發(fā)送蔬捷,只到輸入886結(jié)束
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建接收端的Socket對象
DatagramSocket ds = new DatagramSocket(12345);
while (true) {
// 創(chuàng)建一個(gè)包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
// 接收數(shù)據(jù)
ds.receive(dp);
// 解析數(shù)據(jù)
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
}
// 釋放資源
// 接收端應(yīng)該一直開著等待接收數(shù)據(jù)垄提,是不需要關(guān)閉
// ds.close();
}
}
public class SendDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建發(fā)送端的Socket對象
DatagramSocket ds = new DatagramSocket();
// 封裝鍵盤錄入數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
// 創(chuàng)建數(shù)據(jù)并打包
byte[] bys = line.getBytes();
// DatagramPacket dp = new DatagramPacket(bys, bys.length,
// InetAddress.getByName("192.168.12.92"), 12345);
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.12.255"), 12345);
// 發(fā)送數(shù)據(jù)
ds.send(dp);
}
// 釋放資源
ds.close();
}
}
用多線程改進(jìn)
public class ReceiveThread implements Runnable {
private DatagramSocket ds;
public ReceiveThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
while (true) {
// 創(chuàng)建一個(gè)包裹
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
// 接收數(shù)據(jù)
ds.receive(dp);
// 解析數(shù)據(jù)
String ip = dp.getAddress().getHostAddress();
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println("from " + ip + " data is : " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class SendThread implements Runnable {
private DatagramSocket ds;
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
// 封裝鍵盤錄入數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
// 創(chuàng)建數(shù)據(jù)并打包
byte[] bys = line.getBytes();
// DatagramPacket dp = new DatagramPacket(bys, bys.length,
// InetAddress.getByName("192.168.12.92"), 12345);
DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("192.168.12.255"), 12306);
// 發(fā)送數(shù)據(jù)
ds.send(dp);
}
// 釋放資源
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ChatRoom {
public static void main(String[] args) throws IOException {
DatagramSocket dsSend = new DatagramSocket();
DatagramSocket dsReceive = new DatagramSocket(12306);
SendThread st = new SendThread(dsSend);
ReceiveThread rt = new ReceiveThread(dsReceive);
Thread t1 = new Thread(st);
Thread t2 = new Thread(rt);
t1.start();
t2.start();
}
}
TCP協(xié)議發(fā)送數(shù)據(jù):
創(chuàng)建發(fā)送端的Socket對象(Socket(String host, int port))
這一步如果成功,就說明連接已經(jīng)建立成功了
獲取輸出流周拐,寫數(shù)據(jù)(public OutputStream getOutputStream())
釋放資源
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建發(fā)送端的Socket對象
// Socket(InetAddress address, int port)
// Socket(String host, int port)
// Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
Socket s = new Socket("192.168.12.92", 8888);
// 獲取輸出流铡俐,寫數(shù)據(jù)
// public OutputStream getOutputStream()
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我來了".getBytes());
// 釋放資源
s.close();
}
}
TCP協(xié)議接收數(shù)據(jù):
創(chuàng)建接收端的Socket對象(ServerSocket(int port))
監(jiān)聽客戶端連接。返回一個(gè)對應(yīng)的Socket對象(public Socket accept())
獲取輸入流妥粟,讀取數(shù)據(jù)顯示在控制臺
釋放資源
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建發(fā)送端的Socket對象
// Socket(InetAddress address, int port)
// Socket(String host, int port)
// Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
Socket s = new Socket("192.168.12.92", 8888);
// 獲取輸出流审丘,寫數(shù)據(jù)
// public OutputStream getOutputStream()
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我來了".getBytes());
// 釋放資源
s.close();
}
}
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建接收端的Socket對象
// ServerSocket(int port)
ServerSocket ss = new ServerSocket(8888);
// 監(jiān)聽客戶端連接。返回一個(gè)對應(yīng)的Socket對象
// public Socket accept()
Socket s = ss.accept(); // 偵聽并接受到此套接字的連接勾给。此方法在連接傳入之前一直阻塞滩报。
// 獲取輸入流,讀取數(shù)據(jù)顯示在控制臺
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys); // 阻塞式方法
String str = new String(bys, 0, len);
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "---" + str);
// 釋放資源
s.close();
// ss.close(); //這個(gè)不應(yīng)該關(guān)閉
}
}
加入消息反饋
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器Socket對象
ServerSocket ss = new ServerSocket(9999);
// 監(jiān)聽客戶端的連接
Socket s = ss.accept(); // 阻塞
// 獲取輸入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys); // 阻塞
String server = new String(bys, 0, len);
System.out.println("server:" + server);
// 獲取輸出流
OutputStream os = s.getOutputStream();
os.write("數(shù)據(jù)已經(jīng)收到".getBytes());
// 釋放資源
s.close();
// ss.close();
}
}
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 9999);
// 獲取輸出流
OutputStream os = s.getOutputStream();
os.write("今天天氣很好,適合睡覺".getBytes());
// 獲取輸入流
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);// 阻塞
String client = new String(bys, 0, len);
System.out.println("client:" + client);
// 釋放資源
s.close();
}
}
鍵盤輸入并傳輸,服務(wù)器打印在控制臺
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器Socket對象
ServerSocket ss = new ServerSocket(22222);
// 監(jiān)聽客戶端連接
Socket s = ss.accept();
// 包裝通道內(nèi)容的流
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
// br.close();
s.close();
// ss.close();
}
}
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 22222);
// 鍵盤錄入數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 把通道內(nèi)的流給包裝一下
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
// 鍵盤錄入數(shù)據(jù)要自定義結(jié)束標(biāo)記
if ("886".equals(line)) {
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
// 釋放資源
// bw.close();
// br.close();
s.close();
}
}
客戶端鍵盤錄入播急,服務(wù)器輸出文本文件
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 23456);
// 封裝鍵盤錄入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 封裝通道內(nèi)的數(shù)據(jù)
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
if ("over".equals(line)) {
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
// bw.close();
// br.close();
s.close();
}
}
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器Socket對象
ServerSocket ss = new ServerSocket(23456);
// 監(jiān)聽客戶端連接
Socket s = ss.accept();
// 封裝通道內(nèi)的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
// 封裝文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
// br.close();
s.close();
// ss.close();
}
}
客戶端文本文件脓钾,服務(wù)器輸出到控制臺
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建Socket對象
Socket s = new Socket("192.168.12.92", 34567);
// 封裝文本文件
BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
// 封裝通道內(nèi)的流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
br.close();
s.close();
}
}
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器Socket對象
ServerSocket ss = new ServerSocket(34567);
// 監(jiān)聽客戶端連接
Socket s = ss.accept();
// 封裝通道內(nèi)的流
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
s.close();
}
}
客戶端上傳文本文件到客戶端
public class UploadClient {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 11111);
// 封裝文本文件
BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
// 封裝通道內(nèi)流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 釋放資源
br.close();
s.close();
}
}
public class UploadServer {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器端的Socket對象
ServerSocket ss = new ServerSocket(11111);
// 監(jiān)聽客戶端連接
Socket s = ss.accept();
// 封裝通道內(nèi)的流
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
// 封裝文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
s.close();
}
}
tcp上傳文件服務(wù)器給出反饋
按照我們正常的思路加入反饋信息,結(jié)果卻沒反應(yīng)桩警,為什么呢?
讀取文本文件是可以以null作為結(jié)束信息的可训,但是呢,通道內(nèi)是不能這樣結(jié)束信息的所以捶枢,服務(wù)器根本就不知道你結(jié)束了握截。而你還想服務(wù)器給你反饋。所以柱蟀,就相互等待了
如何解決呢
在多寫一條數(shù)據(jù)川蒙,告訴服務(wù)器,讀取到這條數(shù)據(jù)說明我就結(jié)束长已,你也結(jié)束吧
這樣做可以解決問題畜眨,但是不好
Socket對象提供了一種解決方案
public void shutdownOutput()
public class UploadClient {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 11111);
// 封裝文本文件
BufferedReader br = new BufferedReader(new FileReader(
"InetAddressDemo.java"));
// 封裝通道內(nèi)流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
//自定義一個(gè)結(jié)束標(biāo)記
// bw.write("over");
// bw.newLine();
// bw.flush();
//Socket提供了一個(gè)終止昼牛,它會通知服務(wù)器你別等了,我沒有數(shù)據(jù)過來了
s.shutdownOutput();
// 接收反饋
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client);
// 釋放資源
br.close();
s.close();
}
}
public class UploadServer {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器端的Socket對象
ServerSocket ss = new ServerSocket(11111);
// 監(jiān)聽客戶端連接
Socket s = ss.accept();// 阻塞
// 封裝通道內(nèi)的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封裝文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
// if("over".equals(line)){
// break;
// }
bw.write(line);
bw.newLine();
bw.flush();
}
// 給出反饋
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
bwServer.write("文件上傳成功");
bwServer.newLine();
bwServer.flush();
// 釋放資源
bw.close();
s.close();
}
}
上傳圖片并反饋
public class UploadClient {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 19191);
// 封裝圖片文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("美女.jpg"));
// 封裝通道內(nèi)的流
BufferedOutputStream bos = newBufferedOutputStream(s.getOutputStream());
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
s.shutdownOutput();
// 讀取反饋
InputStream is = s.getInputStream();
byte[] bys2 = new byte[1024];
int len2 = is.read(bys2);
String client = new String(bys2, 0, len2);
System.out.println(client);
// 釋放資源
bis.close();
s.close();
}
}
public class UploadServer {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器Socket對象
ServerSocket ss = new ServerSocket(19191);
// 監(jiān)聽客戶端連接
Socket s = ss.accept();
// 封裝通道內(nèi)流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
// 封裝圖片文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mn.jpg"));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
// 給一個(gè)反饋
OutputStream os = s.getOutputStream();
os.write("圖片上傳成功".getBytes());
bos.close();
s.close();
}
}
多客戶端上傳服務(wù)器案例多線程
public class UserThread implements Runnable {
private Socket s;
public UserThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
// 封裝通道內(nèi)的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 封裝文本文件
// BufferedWriter bw = new BufferedWriter(new
// FileWriter("Copy.java"));
// 為了防止名稱沖突
String newName = System.currentTimeMillis() + ".java";
BufferedWriter bw = new BufferedWriter(new FileWriter(newName));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
// 給出反饋
BufferedWriter bwServer = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
bwServer.write("文件上傳成功");
bwServer.newLine();
bwServer.flush();
// 釋放資源
bw.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class UploadClient {
public static void main(String[] args) throws IOException {
// 創(chuàng)建客戶端Socket對象
Socket s = new Socket("192.168.12.92", 11111);
// 封裝文本文件
// BufferedReader br = new BufferedReader(new FileReader(
// "InetAddressDemo.java"));
BufferedReader br = new BufferedReader(new FileReader(
"ReceiveDemo.java"));
// 封裝通道內(nèi)流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) { // 阻塞
bw.write(line);
bw.newLine();
bw.flush();
}
// Socket提供了一個(gè)終止康聂,它會通知服務(wù)器你別等了贰健,我沒有數(shù)據(jù)過來了
s.shutdownOutput();
// 接收反饋
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client);
// 釋放資源
br.close();
s.close();
}
}
public class UploadServer {
public static void main(String[] args) throws IOException {
// 創(chuàng)建服務(wù)器Socket對象
ServerSocket ss = new ServerSocket(11111);
while (true) {
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
Day27
反射
就是通過class文件對象,去使用該文件中的成員變量恬汁,構(gòu)造方法伶椿,成員方法
使用一個(gè)類的功能之前的做法:
Person p = new Person();
p.使用
要想這樣使用,首先你必須得到class文件對象氓侧,其實(shí)也就是得到Class類的對象
Class類:
成員變量 Field
構(gòu)造方法 Constructor
成員方法 Method
獲取class(字節(jié)碼)文件對象的方式:
Object類的getClass()方法
數(shù)據(jù)類型的靜態(tài)屬性class
Class類中的靜態(tài)方法
public static Class forName(String className) 必須是帶包的路徑脊另,開發(fā)中推薦使用這個(gè)
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1
Person p = new Person();
Class c = p.getClass();
Person p2 = new Person();
Class c2 = p2.getClass();
System.out.println(p == p2);// false
System.out.println(c == c2);// true
// 方式2
Class c3 = Person.class;
// int.class;
// String.class;
System.out.println(c == c3);
// 方式3
// ClassNotFoundException
Class c4 = Class.forName("a.b.Person");
System.out.println(c == c4);
}
}
獲取構(gòu)造方法
public Constructor[] getConstructors():所有公共構(gòu)造方法
public Constructor[] getDeclaredConstructors():所有構(gòu)造方法
獲取單個(gè)構(gòu)造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
參數(shù)表示的是:你要獲取的構(gòu)造方法的構(gòu)造參數(shù)個(gè)數(shù)及數(shù)據(jù)類型的class字節(jié)碼文件對象
public T newInstance(Object... initargs)
使用此 Constructor 對象表示的構(gòu)造方法來創(chuàng)建該構(gòu)造方法的聲明類的新實(shí)例,并用指定的初始化參數(shù)初始化該實(shí)例约巷。
//通過反射獲取構(gòu)造方法并使用
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 獲取字節(jié)碼文件對象
Class c = Class.forName("a.b.Person");
// 獲取構(gòu)造方法
// public Constructor[] getConstructors():所有公共構(gòu)造方法
// public Constructor[] getDeclaredConstructors():所有構(gòu)造方法
// Constructor[] cons = c.getDeclaredConstructors();
// for (Constructor con : cons) {
// System.out.println(con);
// }
// 獲取單個(gè)構(gòu)造方法
// public Constructor<T> getConstructor(Class<?>... parameterTypes)
// 參數(shù)表示的是:你要獲取的構(gòu)造方法的構(gòu)造參數(shù)個(gè)數(shù)及數(shù)據(jù)類型的class字節(jié)碼文件對象
Constructor con = c.getConstructor();// 返回的是構(gòu)造方法對象
// Person p = new Person();
// System.out.println(p);
// public T newInstance(Object... initargs)
// 使用此 Constructor 對象表示的構(gòu)造方法來創(chuàng)建該構(gòu)造方法的聲明類的新實(shí)例偎痛,并用指定的初始化參數(shù)初始化該實(shí)例。
Object obj = con.newInstance();
System.out.println(obj);
// Person p = (Person)obj;
// p.show();
}
}
獲取帶參構(gòu)造
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
// 獲取字節(jié)碼文件對象
Class c = Class.forName("a.b.Person");
// 獲取帶參構(gòu)造方法對象
// public Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor(String.class, int.class,String.class);
// 通過帶參構(gòu)造方法對象創(chuàng)建對象
// public T newInstance(Object... initargs)
Object obj = con.newInstance("張三", 18, "北京");
System.out.println(obj);
}
}
通過反射獲取私有構(gòu)造方法并使用
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
// 獲取字節(jié)碼文件對象
Class c = Class.forName("cn.itcast_01.Person");
// 獲取私有構(gòu)造方法對象
// NoSuchMethodException:每個(gè)這個(gè)方法異常
// 原因是一開始我們使用的方法只能獲取公共的独郎,下面這種方式就可以了踩麦。
Constructor con = c.getDeclaredConstructor(String.class);
// 用該私有構(gòu)造方法創(chuàng)建對象
// IllegalAccessException:非法的訪問異常。
// 暴力訪問
con.setAccessible(true);// 值為true則指示反射的對象在使用時(shí)應(yīng)該取消Java語言訪問檢查氓癌。
Object obj = con.newInstance("張三");
System.out.println(obj);
}
}
通過反射獲取成員變量并使用
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 獲取字節(jié)碼文件對象
Class c = Class.forName("cn.itcast_01.Person");
// 獲取所有的成員變量
// Field[] fields = c.getFields();公共的
// Field[] fields = c.getDeclaredFields();所有的谓谦,包括私有
// for (Field field : fields) {
// System.out.println(field);
// }
/*
* Person p = new Person(); p.address = "北京"; System.out.println(p);
*/
// 通過無參構(gòu)造方法創(chuàng)建對象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
// 獲取單個(gè)的成員變量
// 獲取address并對其賦值
Field addressField = c.getField("address");
// public void set(Object obj,Object value)
// 將指定對象變量上此 Field 對象表示的字段設(shè)置為指定的新值。
addressField.set(obj, "北京"); // 給obj對象的addressField字段設(shè)置值為"北京"
System.out.println(obj);
// 獲取name并對其賦值
// NoSuchFieldException
Field nameField = c.getDeclaredField("name");
// IllegalAccessException
nameField.setAccessible(true);
nameField.set(obj, "張三");
System.out.println(obj);
// 獲取age并對其賦值
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj, 27);
System.out.println(obj);
}
}
通過反射獲取成員方法并使用
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 獲取字節(jié)碼文件對象
Class c = Class.forName("cn.itcast_01.Person");
// 獲取所有的方法
// Method[] methods = c.getMethods(); // 獲取自己的包括父親的公共方法
// Method[] methods = c.getDeclaredMethods(); // 獲取自己的所有的方法
// for (Method method : methods) {
// System.out.println(method);
// }
Constructor con = c.getConstructor();
Object obj = con.newInstance();
/*
* Person p = new Person(); p.show();
*/
// 獲取單個(gè)方法并使用
// public void show()
// public Method getMethod(String name,Class<?>... parameterTypes)
// 第一個(gè)參數(shù)表示的方法名贪婉,第二個(gè)參數(shù)表示的是方法的參數(shù)的class類型
Method m1 = c.getMethod("show");
// obj.m1(); // 錯(cuò)誤
// public Object invoke(Object obj,Object... args)
// 返回值是Object接收,第一個(gè)參數(shù)表示對象是誰反粥,第二參數(shù)表示調(diào)用該方法的實(shí)際參數(shù)
m1.invoke(obj); // 調(diào)用obj對象的m1方法
System.out.println("----------");
// public void method(String s)
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "hello");
System.out.println("----------");
// public String getString(String s, int i)
Method m3 = c.getMethod("getString", String.class, int.class);
Object objString = m3.invoke(obj, "hello", 100);
System.out.println(objString);
// String s = (String)m3.invoke(obj, "hello",100);
// System.out.println(s);
System.out.println("----------");
// private void function()
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}
}
反射的應(yīng)用
通過配置文件運(yùn)行類中的方法
反射:
需要有配置文件配合使用,用class.txt代替
并且你知道有兩個(gè)鍵
className
methodName
//假設(shè)有學(xué)生類谓松,老師類星压,工人類践剂,每個(gè)類都有一個(gè)方法love();實(shí)現(xiàn)不同的功能
public class Test {
public static void main(String[] args) throws Exception {
// 反射前的做法鬼譬,每個(gè)類都要?jiǎng)?chuàng)建對象,在調(diào)用方法逊脯,假設(shè)根據(jù)需求每次更換一個(gè)類執(zhí)行优质,就很麻煩
// Student s = new Student();
// s.love();
// Teacher t = new Teacher();
// t.love();
// Worker w = new Worker();
// w.love();
// 反射后的做法
// 加載鍵值對數(shù)據(jù)
Properties prop = new Properties();
FileReader fr = new FileReader("class.txt");//根據(jù)Class.txt里邊的鍵值對,決定是哪個(gè)類军洼,執(zhí)行那個(gè)方法巩螃,需求變了需要換類換方法,只需要更改Class.txt里邊的
prop.load(fr);
fr.close();
// 獲取數(shù)據(jù)
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
// 反射
Class c = Class.forName(className);
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 調(diào)用方法
Method m = c.getMethod(methodName);
m.invoke(obj);
}
}
/*
* 我給你ArrayList<Integer>的一個(gè)對象匕争,我想在這個(gè)集合中添加一個(gè)字符串?dāng)?shù)據(jù)避乏,如何實(shí)現(xiàn)呢?
*/
public class ArrayListDemo {
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
// 創(chuàng)建集合對象
ArrayList<Integer> array = new ArrayList<Integer>();
// array.add("hello");
// array.add(10);
Class c = array.getClass(); // 集合ArrayList的class文件對象
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello"); // 調(diào)用array的add方法甘桑,傳入的值是hello
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
}
}
修改任意類的任意成員變量所對應(yīng)的值
public class Tool {
public void setProperty(Object obj, String propertyName, Object value)
throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
// 根據(jù)對象獲取字節(jié)碼文件對象
Class c = obj.getClass();
// 獲取該對象的propertyName成員變量
Field field = c.getDeclaredField(propertyName);
// 取消訪問檢查
field.setAccessible(true);
// 給對象的成員變量賦值為指定的值
field.set(obj, value);
}
}
public class ToolDemo {
public static void main(String[] args) throws NoSuchFieldException,
SecurityException, IllegalArgumentException, IllegalAccessException {
Person p = new Person();
Tool t = new Tool();
t.setProperty(p, "name", "張三");
t.setProperty(p, "age", 27);
System.out.println(p);
System.out.println("-----------");
Dog d = new Dog();
t.setProperty(d, "sex", '男');
t.setProperty(d, "price", 12.34f);
System.out.println(d);
}
}
class Dog {
char sex;
float price;
@Override
public String toString() {
return sex + "---" + price;
}
}
class Person {
private String name;
public int age;
@Override
public String toString() {
return name + "---" + age;
}
}