2022-04-04

定時(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;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拍皮,一起剝皮案震驚了整個(gè)濱河市歹叮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铆帽,老刑警劉巖咆耿,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異爹橱,居然都是意外死亡萨螺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門愧驱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慰技,“玉大人,你說我怎么就攤上這事组砚∪桥危” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵惫确,是天一觀的道長手报。 經(jīng)常有香客問我,道長改化,這世上最難降的妖魔是什么掩蛤? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮陈肛,結(jié)果婚禮上揍鸟,老公的妹妹穿的比我還像新娘。我一直安慰自己句旱,他們只是感情好阳藻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谈撒,像睡著了一般腥泥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啃匿,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天蛔外,我揣著相機(jī)與錄音,去河邊找鬼溯乒。 笑死夹厌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裆悄。 我是一名探鬼主播矛纹,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼光稼!你這毒婦竟也來了或南?” 一聲冷哼從身側(cè)響起逻住,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迎献,沒想到半個(gè)月后瞎访,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吁恍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年扒秸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冀瓦。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伴奥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翼闽,到底是詐尸還是另有隱情拾徙,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布感局,位于F島的核電站尼啡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏询微。R本人自食惡果不足惜崖瞭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撑毛。 院中可真熱鬧书聚,春花似錦、人聲如沸藻雌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背燃异。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崇呵,地道東北人江掩。 一個(gè)月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像核畴,于是被迫代替她去往敵國和親膝但。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354