Java核心類庫(下篇)

第十六章 異常機制和file類

16.1 異常機制(重點)

16.1.1 基本概念

  • 所謂的異常就是Java程序在運行過程中發(fā)生了錯誤,出現(xiàn)了不正常的行為流炕,中斷正在執(zhí)行程序的正常指令流澎现;

  • Java.lang.Throwable類是Java中Error和Exception的基類;

  • Error稱為錯誤每辟,主要是一些JVM層面的錯誤剑辫,程序開發(fā)人員是無法通過程序去處理的,只能重啟JVM渠欺。例如堆棧溢出妹蔽。

  • Exception稱為異常,主要是一些程序設(shè)計不嚴(yán)謹(jǐn)所拋出一些異常情況,開發(fā)人員可以事先通過編碼去捕獲處理胳岂。例如典型的空指針異常(NullPointException)编整。

16.1.2 異常的分類

  • Throwable類URL圖
Throwable結(jié)構(gòu)圖.png

上圖所示

異常的分類主要分類兩種:

  • RuntimeException 非檢測性異常

  • IOException和其他異常 檢測性異常

判斷檢測性異常和非檢測性異常的區(qū)別:非檢測性異常編譯器無法識別,只有在程序運行的過程中才會發(fā)現(xiàn)乳丰;檢測性
異常是編譯器能夠發(fā)現(xiàn)的

  • 代碼demo
System.out.println("-----------非檢測性異常----------");
/**
 * 此時編譯器并沒有提示報錯掌测,運行時會拋出Exception in thread "main" java.lang.ArithmeticException: / by zero
 */
System.out.println(4 / 0);

System.out.println("-----------檢測性異常------------");
/**
 * 會有紅色波浪線提示unhandledException,此時需要捕獲處理
 */
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
  • 注意

一旦程序拋出異常产园,拋出異常地方下面的程序都不會再執(zhí)行汞斧。

16.1.3 異常避免

  • 通常程序開發(fā)使用if判斷語句進行避免異常的發(fā)生

  • 缺點:代碼可讀性差,臃腫

  • 代碼demo

System.out.println("-------------算術(shù)異常------------");
int a = 8;
int b = 0;
if (0 != b) {
    System.out.println(a / b);
}

System.out.println("------------下標(biāo)越界異常--------");
int[] arr = new int[5];
int index = 5;
if (arr.length > 0 && arr.length < 5) {
    System.out.println(arr);
}

System.out.println("-------------空指針異常----------");
String str = null;
if (null != str) {
    System.out.println(str.length());
}

System.out.println("------------類型轉(zhuǎn)換異常---------");
Object it = new Object();
if(it instanceof String) {
    String c = (String) it;
}

System.out.println("------------數(shù)據(jù)格式異常---------");
String numStr = "123r";
if (numStr.matches("\\d+")) {
    int i = Integer.parseInt(numStr);
    System.out.println(i);
}

16.1.6 自定義異常

  • 自定義異常類
public class AgeException extends Exception{

    /**
     * 自定義異常AgeException什燕,用于判斷用戶年齡是否符合要求
     */
    public AgeException() {
        super();
    }

    public AgeException(String message) {
        super(message);
    }
}
  • 學(xué)生類
private String name;

private int age;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}


/**
 * 使用throw進行聲明異常
 *
 * @param age
 * @throws AgeException
 */
public void setAge(int age) throws AgeException {
    if (age > 0 && age < 120) {
        this.age = age;
    } else {
        throw new AgeException("年齡不合理");
    }

}

public Student(String name, int age) throws AgeException {
    setName(name);
    setAge(age);
}


@Override
public String toString() {
    return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}
  • 測試結(jié)果類
/**
 * 1. 當(dāng)使用throw的方式進行將一場進行跑出去的時候断箫,由調(diào)用者進行try-catch進行捕獲進行處理的時候,一旦發(fā)生異常就不會生成對象
 *
 * 打印結(jié)果:
 *
 * student1 = Student{name='fuyi', age=10}
 * com.ryan.stage1.model4.task16.AgeException: 年齡不合理
 *  at com.ryan.stage1.model4.task16.Student.setAge(Student.java:32)
 *  at com.ryan.stage1.model4.task16.Student.<init>(Student.java:39)
 *  at com.ryan.stage1.model4.task16.StudentTest.main(StudentTest.java:13)
 */
try {
    Student student1 = new Student("fuyi", 10);
    System.out.println("student1 = " + student1);
    Student student2 = new Student("Sam", 130);
    System.out.println("student2  =" + student2);
} catch (AgeException e) {
    e.printStackTrace();
}
  • 使用try-catch方式
private String name;

private int age;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}


/**
 * 使用throw進行聲明異常
 *
 * @param age
 * @throws AgeException
 */
public void setAge(int age) throws AgeException {
    if (age > 0 && age < 120) {
        this.age = age;
    } else {
        throw new AgeException("年齡不合理");
    }

}


public Student(String name, int age) {
    setName(name);
    try {
        setAge(age);
    } catch (AgeException e) {
        e.printStackTrace();
    }
}

@Override
public String toString() {
    return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
  • 測試結(jié)果
/**
 * 2. 如果在方法本身內(nèi)部使用try-catch進行捕獲處理秋冰,對象還是會生成
 *
 * 打印結(jié)果:
 * com.ryan.stage1.model4.task16.AgeException: 年齡不合理
 *  at com.ryan.stage1.model4.task16.Student.setAge(Student.java:32)
 *  at com.ryan.stage1.model4.task16.Student.<init>(Student.java:45)
 *  at com.ryan.stage1.model4.task16.StudentTest.main(StudentTest.java:22)
 * student3 = Student{name='Lucy', age=0}
 */
Student student3 = new Student("Lucy", 123);
System.out.println("student3 = " + student3);
  • 總結(jié)

使用throw和try-catch的區(qū)別: 在于try-catch還是可以進行對象的生成仲义,而使用throw進行拋出異常的時候,此時對象不會生成而為null剑勾。

16.2 File類

16.2.1 基本概念

java.io.File類主要用于描述文件或目錄路徑的抽象表示信息埃撵,可以獲取文件或目錄的特征信息,
如:大小等虽另。

16.2.2 常用的方法

方法聲明 功能概述
File(String pathname) 根據(jù)參數(shù)指定的路徑名來構(gòu)造對象
File(String parent, String child) 根據(jù)參數(shù)指定的父路徑和子路徑信息構(gòu)造對象
File(File parent, String child) 根據(jù)參數(shù)指定的父抽象路徑和子路徑信息構(gòu)造對象
boolean exists() 測試此抽象路徑名表示的文件或目錄是否存在
String getName() 用于獲取文件的名稱
long length() 返回由此抽象路徑名表示的文件的長度
long lastModified() 用于獲取文件的最后一次修改時間
String getAbsolutePath() 用于獲取絕對路徑信息
boolean delete() 用于刪除文件暂刘,當(dāng)刪除目錄時要求是空目錄
boolean createNewFile() 用于創(chuàng)建新的空文件
boolean mkdir() 用于創(chuàng)建目錄
boolean mkdirs() 用于創(chuàng)建多級目錄
File[] listFiles() 獲取該目錄下的所有內(nèi)容
boolean isFile() 判斷是否為文件
boolean isDirectory() 判斷是否為目錄
File[] listFiles(FileFilter filter) 獲取目錄下滿足篩選器的所有內(nèi)容

第十七章 IO流

17.1 IO流的概念

  • IO就是Input和Output的簡寫。

  • IO流就是是Java程序讀寫數(shù)據(jù)的一種方式捂刺。流是一種有序的數(shù)據(jù)序列谣拣,將數(shù)據(jù)從一個地方帶到另一個地方。

17.2 基本分類

  • 按流的方向

    • 輸出流族展,從程序到文件森缠、網(wǎng)絡(luò)、數(shù)據(jù)庫和其他數(shù)據(jù)源

    • 輸入流仪缸,從文件贵涵、網(wǎng)絡(luò)、數(shù)據(jù)庫和其他數(shù)據(jù)源到程序

    • 如下圖所示

  • 按流的數(shù)據(jù)單位

    • 字節(jié)流恰画,以字節(jié)(8位)為單位進行數(shù)據(jù)的讀寫宾茂,可以讀寫任意類型的文件。

    • 字符流拴还,以字符(2個字節(jié))為單位進行數(shù)據(jù)的讀寫跨晴,只能讀取文本文件。

  • 按流的功能

    • 節(jié)點流片林,就是指直接和輸入輸出源對接的流端盆。

    • 處理流树瞭,指建立在在節(jié)點流的基礎(chǔ)上的流。

17.3 體系結(jié)構(gòu)

流的體系結(jié)構(gòu).png

17.4 相關(guān)流的詳解

  • 流體系框架圖

17.4.1 FileWriter類(重點)

  • 作用

java.lang.FileWriter類主要用于將文本內(nèi)容寫入到文本文件

  • 常用構(gòu)造方法
方法聲明 功能
FileWriter?(File file) 使用平臺的默認(rèn)字符集構(gòu)造給定要寫入文件的FileWriter
FileWriter?(File file, boolean append) 使用平臺的默認(rèn)字符集爱谁,構(gòu)造一個FileWriter晒喷,給定要寫入的File和一個布爾值,該布爾值指示是否追加寫入的數(shù)據(jù)访敌。
FileWriter?(File file, Charset charset) 給定File來構(gòu)造FileWriter進行寫和字符集設(shè)置凉敲。

代碼demo

FileWriter fileWriter1 = null;
FileWriter fileWriter2 = null;
try {
    //1. 構(gòu)造方法一
    fileWriter1 = new FileWriter("U:\\Ryan\\lagou-basic\\stage1\\src\\main\\java\\com\\ryan\\stage1\\model4\\task17\\file");

    //2. 構(gòu)造方法二(內(nèi)容追加方式)
    fileWriter2 = new FileWriter("U:\\Ryan\\lagou-basic\\stage1\\src\\main\\java\\com\\ryan\\stage1\\model4\\task17\\file", true);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fileWriter1 != null || fileWriter2 != null) {
        //關(guān)閉資源
        try {
            fileWriter1.close();
            fileWriter2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用方法

代碼demo

System.out.println("--------------------------FileWriter類常用方法--------------------------------------");

/**
 *  1. 寫入單個字符,
 */
fileWriter1.write("B");                      // B

/**
 * 2. 將指定字符數(shù)組中從偏移量off開始的len個字符寫入此文件輸出流
 */
char[] cArr = new char[]{'a', 'b', 'c', 'd'};
fileWriter1.write(cArr, 1, 3);        // bcd

/**
 * 3. 將cbuf.length個字符從指定字符數(shù)組寫入此文件輸出流中
 */
fileWriter1.write(cArr);                      // bcdabcd

/**
 * 4. 刷新流
 */
fileWriter1.flush();

/**
 * 5. 關(guān)閉流對象釋放有關(guān)的資源
 */
fileWriter1.close();

17.4.2 FileReader類(重點)

  • 作用

java.lang.FileReader類主要用于從文本文件讀取文本數(shù)據(jù)內(nèi)容

  • 常用構(gòu)造方法

代碼demo

System.out.println("-------------構(gòu)造方法-----------------");
//1. 構(gòu)造方法一
FileReader fileReader1 = null;

try {
    fileReader1 = new FileReader("U:/Ryan/lagou-basic/stage1//src/main/java/com/ryan/stage1/model4/task17/file/myFile.txt");
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (fileReader1 != null) {
        try {
            fileReader1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用類方法

代碼demo

System.out.println("----------------常用方法-------------------------");

/**
 * 1. 讀取單個字符的數(shù)據(jù)并返回,返回-1表示讀取到末尾
 */
int read = fileReader1.read();
System.out.println((char) read);               // B

/**
 * 2. 讀取全部
 */
while (fileReader1.read() != -1) {
    int read1 = fileReader1.read();
    System.out.println("字符為:" + (char) read1);
}

/**
 * 3. 從輸入流中將最多l(xiāng)en個字符的數(shù)據(jù)讀入一個字符數(shù)組中,返回讀取到的字符個數(shù)蝉衣,返回-1表示讀取到末尾
 */
char[] cArr = new char[5];
fileReader1.read(cArr, 0, 5);
System.out.println(cArr);                      // Bbcda

 /** 4. 關(guān)閉流對象措伐,釋放資源
  */
fileReader1.close();

17.4.3 FileOutputStream類(重點)

上述的兩個類主要對文件進行讀寫操作圾浅,但是對于音頻和視頻是不能進行讀寫,就算讀寫成功也是解析不出來,因此下面介紹能夠讀取任意文件類型的
文件流類

  • 作用

java.io.FileOutputStream類主要用于將圖像數(shù)據(jù)之類的原始字節(jié)流寫入到輸出流中。

  • 構(gòu)造方法

代碼demo

System.out.println("-------------------構(gòu)造方法-----------------------");

FileOutputStream fileOutputStream1 = null;
FileOutputStream fileOutputStream2 = null;

/**
 * 創(chuàng)建文件輸出流以寫入具有指定名稱的文件
 */
try {
    //1. 構(gòu)造一 (如果文件不存在會自動創(chuàng)建一個空白文件)
    fileOutputStream1 = new FileOutputStream("e:/myFile.txt");

    //2. 構(gòu)造二 (進行追加內(nèi)容)
    fileOutputStream2 = new FileOutputStream("e:/myFile.txt",true);
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (null != fileOutputStream1) {
        try {
            fileOutputStream1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (null != fileOutputStream2) {
        try {
            fileOutputStream2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用方法
System.out.println("-------------------構(gòu)造方法-----------------------");

FileOutputStream fileOutputStream1 = null;
FileOutputStream fileOutputStream2 = null;

/**
 * 創(chuàng)建文件輸出流以寫入具有指定名稱的文件
 */
try {
    //1. 構(gòu)造一 (如果文件不存在會自動創(chuàng)建一個空白文件)
    fileOutputStream1 = new FileOutputStream("e:/myFile.txt");

    //2. 構(gòu)造二 (進行追加內(nèi)容)
    fileOutputStream2 = new FileOutputStream("e:/myFile.txt",true);

    System.out.println("--------------------常用方法----------------------");

    /**
     * 1. 將指定字節(jié)寫入此文件輸出流
     */
    fileOutputStream1.write('G');

    /**
     * 2. 將指定字節(jié)數(shù)組中從偏移量off開始的len個字節(jié)寫入此文件輸出流
     */
    byte[] arr = new byte[] {65, 66, 67, 68};
    fileOutputStream1.write(arr);

    /**
     * 3. 刷新此輸出流并強制寫出任何緩沖的輸出字節(jié)
     */
    fileOutputStream1.flush();

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != fileOutputStream1) {
        try {
            /**
             * 4. 關(guān)閉流對象并釋放有關(guān)的資源
             */
            fileOutputStream1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (null != fileOutputStream2) {
        try {
            fileOutputStream2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 總結(jié)

17.4.4 FileInputStream類(重點)

  • 作用

java.io.FileInputStream類主要用于從輸入流中以字節(jié)流的方式讀取圖像數(shù)據(jù)等渤昌。

  • 構(gòu)造方法

代碼demo

System.out.println("-----------------構(gòu)造方法------------------------");
        FileInputStream fileInputStream1 = null;

        try {
            fileInputStream1= new FileInputStream("e:/myFile.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (null != fileInputStream1) {
                try {
                    /**
                     * 4. 關(guān)閉流對象并釋放有關(guān)的資源
                     */
                    fileInputStream1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
  • 常用方法
System.out.println("-----------------構(gòu)造方法------------------------");
FileInputStream fileInputStream1 = null;

try {
    fileInputStream1= new FileInputStream("e:/myFile.txt");

    System.out.println("----------------常用方法----------------------");

    /**
     * 1. 從輸入流中讀取單個字節(jié)的數(shù)據(jù)并返回,返回-1表示讀取到末尾
     * 注意:這里調(diào)用read()方法和迭代器itertor.next()方法是一樣走搁,每調(diào)用一次独柑,游標(biāo)向下移動一次
     */
    int read = fileInputStream1.read();
    System.out.println((char) read);

    while ((read = fileInputStream1.read()) != -1) {
        System.out.println((char) read);                              // A B C D
    }

    while (fileInputStream1.read() != -1) {
        System.out.println((char) fileInputStream1.read());           // B D
    }

    /**
     * 2. 從此輸入流中將最多 b.length 個字節(jié)的數(shù)據(jù)讀入字節(jié)數(shù)組中,返回讀取到的字節(jié)個數(shù)私植,返回-1表示讀取到末尾
     */
    byte[] brr = new byte[5];
    fileInputStream1.read(brr);
    for (byte b : brr) {
        System.out.print(b);                                         // 71 65 66 67 68
    }

    /**
     * 3. 獲取輸入流所關(guān)聯(lián)文件的大小
     */
    System.out.println("輸入流大小為:" + fileInputStream1.available());// 5
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != fileInputStream1) {
        try {
            /**
             * 4. 關(guān)閉流對象并釋放有關(guān)的資源
             */
            fileInputStream1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 文件拷貝
//測試拷貝效率
long start = System.currentTimeMillis();
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;

try {
    //1. 創(chuàng)建文件輸入流
    fileInputStream = new FileInputStream("e:/myFile.txt");

    //2. 創(chuàng)建文件輸出流
    fileOutputStream = new FileOutputStream("e:/myFileCopys.txt");

    //3. 讀取一個字節(jié)然后寫入一個字節(jié)
    int read = 0;
    while ((read = fileInputStream.read()) != -1) {
        fileOutputStream.write(read);
    }

    //4. 使用緩存分多少次進行讀寫
    byte[] brr = new byte[1024];
    int length = 0;
    while ((length = fileInputStream.read(brr)) != -1) {
        fileOutputStream.write(brr, 0, length);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    //關(guān)閉資源
    if (null != fileInputStream)  {
        try {
            fileInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (null != fileOutputStream)  {
        try {
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
long end = System.currentTimeMillis();
System.out.println("Copy消耗時間" + (end - start) + "ms");          //9ms
System.out.println("緩存方式Copy消耗時間" + (end - start) + "ms");   //1ms
  • 總結(jié)

    • 這里調(diào)用read()方法和迭代器itertor.next()方法是一樣忌栅,每調(diào)用一次,游標(biāo)向下移動一次曲稼;讀取完后想要重新再讀取一遍需要重新創(chuàng)建一個流對象

    • 通過上面兩個類可以實現(xiàn)文件的拷貝索绪,拷貝的方式有三種:第一種是逐個字節(jié)讀取并寫入,缺點就是文件過大時候贫悄,花費時間很長瑞驱;
      第二種是通過將文件讀入到一個文件大小的字節(jié)數(shù)組緩沖區(qū)里面,讀取完畢再一并寫入清女,缺點就是文件過大占用較大的物理內(nèi)存空間钱烟;
      第三種是在第二種的基礎(chǔ)上通過分批多次讀取并寫入,相對前面兩種來說效率得到提升和資源開銷也減少了嫡丙。

17.4.5 BufferedOutputStream類(重點)

上面章節(jié)結(jié)束的時候,我們使用自定義緩存的方式進行讀寫copy文件读第,Java官方也提供了這種緩存式的讀寫操作的類曙博。本章節(jié)就繼續(xù)討論緩存式讀寫操作類

  • 作用

java.io.BufferedOutputStream類主要用于描述緩沖輸出流,此時不用為寫入的每個字節(jié)調(diào)用底層系統(tǒng)怜瞒。

  • 構(gòu)造方法

代碼demo

BufferedOutputStream bos = null;

System.out.println("---------------------構(gòu)造方法---------------------------");
try {
    // 1.創(chuàng)建BufferedOutputStream類型的對象與e:/myFile.txt流的框架結(jié)構(gòu).txt文件關(guān)聯(lián)
    bos = new BufferedOutputStream(new FileOutputStream("e:/myFile.txt"));
} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 4.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != bos) {
        try {
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用方法
BufferedOutputStream bos = null;

System.out.println("---------------------構(gòu)造方法---------------------------");
try {
    // 1.創(chuàng)建BufferedOutputStream類型的對象與e:/myFile.txt流的框架結(jié)構(gòu).txt文件關(guān)聯(lián)
    bos = new BufferedOutputStream(new FileOutputStream("e:/myFile.txt"));

    System.out.println("--------------------常用方法----------------------");

    /**
     * 1. 將指定字節(jié)寫入此文件輸出流
     */
    bos.write('G');

    /**
     * 2. 將指定字節(jié)數(shù)組中從偏移量off開始的len個字節(jié)寫入此文件輸出流
     */
    byte[] arr = new byte[] {65, 66, 67, 68};
    bos.write(arr);

    /**
     * 3. 刷新此輸出流并強制寫出任何緩沖的輸出字節(jié)
     */
    bos.flush();

} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 4.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != bos) {
        try {
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 總結(jié)

    和上面的的流對象相比父泳,只是構(gòu)造方法的不同般哼,其他的常用方法都是一樣,后就不再加以贅述了惠窄。

17.4.6 BufferedInputStream類(重點)

  • 作用

java.io.BufferedInputStream類主要用于描述緩沖輸入流蒸眠。

  • 構(gòu)造方法

代碼demo

BufferedInputStream bis = null;

System.out.println("-------------------構(gòu)造方法-------------------");

try {
    new BufferedInputStream(new FileInputStream("e:/myFile.txt"));
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (null != bis) {
        try {
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用方法
參考FileInputStream
  • 文件拷貝
// 獲取當(dāng)前系統(tǒng)時間距離1970年1月1日0時0分0秒的毫秒數(shù)
long g1 = System.currentTimeMillis();

BufferedInputStream bis = null;
BufferedOutputStream bos = null;

try {
    // 1.創(chuàng)建BufferedInputStream類型的對象與e:/myFile.txt文件關(guān)聯(lián)
    bis = new BufferedInputStream(new FileInputStream("e:/myFile.txt"));
    // 2.創(chuàng)建BufferedOuputStream類型的對象與e:/myFileCopys.txt文件關(guān)聯(lián)
    bos = new BufferedOutputStream(new FileOutputStream("e:/myFileCopys.txt"));

    // 3.不斷地從輸入流中讀取數(shù)據(jù)并寫入到輸出流中

    byte[] bArr = new byte[1024];
    int res = 0;
    while ((res = bis.read(bArr)) != -1) {
        bos.write(bArr, 0, res);
    }

} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 4.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != bos) {
        try {
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (null != bis) {
        try {
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

long g2 = System.currentTimeMillis();
System.out.println("使用緩沖區(qū)拷貝文件消耗的時間為:" + (g2-g1)); // 1ms

17.4.7 BufferedWrite類(重點)

  • 作用

java.io.BufferedWriter類主要用于寫入單個字符、字符數(shù)組以及字符串到輸出流中杆融。

  • 構(gòu)造方法

代碼demo

System.out.println("-----------構(gòu)造方法--------------");

BufferedWriter bufferedWriter1 = null;

try {
    bufferedWriter1 = new BufferedWriter(new FileWriter("e:/myFile.txt"));
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != bufferedWriter1) {
        try {
            /**
             * 6. 關(guān)閉資源
             */
            bufferedWriter1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
  • 常用方法
System.out.println("-----------構(gòu)造方法--------------");

BufferedWriter bufferedWriter1 = null;

try {
    bufferedWriter1 = new BufferedWriter(new FileWriter("e:/myFile.txt"));

    System.out.println("-------常用方法--------------");

    /**
     * 1. 寫入單個字符到輸出流中
     */
    bufferedWriter1.write(70);

    /**
     * 2. 將字符串?dāng)?shù)組cbuf中所有內(nèi)容寫入輸出流中
     */
    char[] cArr = new char[] {'b', 'n', 'y'};
    bufferedWriter1.write(cArr);

    /**
     * 3. 將參數(shù)指定的字符串內(nèi)容寫入輸出流中
     */
    bufferedWriter1.write("fuyi");

    /**
     * 4. 用于寫入行分隔符到輸出流中
     */
    bufferedWriter1.newLine();

    bufferedWriter1.write(cArr);

    /**
     * 5. 刷新流
     */
    bufferedWriter1.flush();


} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != bufferedWriter1) {
        try {
            /**
             * 6. 關(guān)閉資源
             */
            bufferedWriter1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
  • 總結(jié)

17.4.8 BufferedRead類(重點)

  • 作用

java.io.BufferedReader類用于從輸入流中讀取單個字符楞卡、字符數(shù)組以及字符串。

  • 構(gòu)造方法

代碼demo

System.out.println("--------------構(gòu)造方法------------------");

BufferedReader bufferedReader1 = null;

try {
    bufferedReader1 = new BufferedReader(new FileReader("e:/myFile.txt"));
    
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (null != bufferedReader1) {
        try {
            bufferedReader1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用方法
BufferedReader bufferedReader1 = null;

try {
    bufferedReader1 = new BufferedReader(new FileReader("e:/myFile.txt"));

    System.out.println("-----------------常用方法---------------");

    /**
     * 1. 從輸入流讀取單個字符脾歇,讀取到末尾則返回-1蒋腮,否則返回實際讀取到的字符內(nèi)容
     */
    int read = bufferedReader1.read();
    System.out.println((char) read);

    /**
     * 2. 從輸入流中讀滿整個數(shù)組cbuf
     */
    char[] crr = new char[5];
    bufferedReader1.read(crr);
    System.out.println(crr);

    /**
     * 3. 讀取一行字符串并返回,返回null表示讀取到末尾
     */
    String str = null;
    while ((str = bufferedReader1.readLine()) != null) {
        System.out.println(str);
    }

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != bufferedReader1) {
        try {
            /**
             * 4. 關(guān)閉資源
             */
            bufferedReader1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 總結(jié)

17.4.9 PrintStream類(重點)

  • 作用

java.io.PrintStream類主要用于更加方便地打印各種數(shù)據(jù)內(nèi)容藕各。

  • 構(gòu)造方法

代碼demo

System.out.println("---------------構(gòu)造方法------------------");

PrintStream printStream1 = null;

try {
    printStream1 = new PrintStream(new FileOutputStream("e:/myFile.txt"));
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (null != printStream1) {
        printStream1.close();
    }
}
  • 常用方法
PrintStream printStream1 = null;

try {
    printStream1 = new PrintStream(new FileOutputStream("e:/myFile.txt"));

    System.out.println("-----------------常用方法-------------------");

    /**
     * 1. 用于將參數(shù)指定的字符串內(nèi)容打印出來
     */
    printStream1.print("fuyinb");

    /**
     * 2. 用于打印字符串后并終止該行
     */
    printStream1.println("cheshigailei");
    printStream1.println("另起一行");

    /**
     * 3. 刷新流
     */
    printStream1.flush();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (null != printStream1) {
        /**
         * 4. 關(guān)閉流
         */
        printStream1.close();
    }
}
  • 總結(jié)

17.4.10 PrintWriter類

  • 作用

java.io.PrintWriter類主要用于將對象的格式化形式打印到文本輸出流池摧。

  • 構(gòu)造方法

代碼demo

System.out.println("-------------------構(gòu)造方法-------------------");

PrintWriter printWriter1 = null;

try {
    printWriter1 = new PrintWriter(new FileWriter("e:/myChat.txt"));
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != printWriter1) {
        printWriter1.close();
    }
}
  • 常用方法
參考PrintWriter類
  • 總結(jié)

17.4.11 OutputStreamWriter類(重點)

  • 作用

java.io.OutputStreamWriter類主要用于實現(xiàn)從字符流到字節(jié)流的轉(zhuǎn)換。

  • 構(gòu)造方法

代碼demo

OutputStreamWriter outputStreamWriter1 = null;
OutputStreamWriter outputStreamWriter2 = null;

try {

    //構(gòu)造方法一
    outputStreamWriter1 = new OutputStreamWriter(new FileOutputStream("e:/myFile.txt"));

    //構(gòu)造方法二
    outputStreamWriter2 = new OutputStreamWriter(new FileOutputStream("e:/myFile.txt"), "utf-8");
   
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != outputStreamWriter1) {
        try {
            /**
             * 3. 關(guān)閉流
             */
            outputStreamWriter1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (null != outputStreamWriter2) {
        try {
            outputStreamWriter2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 常用方法

System.out.println("------------------常用方法-------------------");

/**
 * 1. 將參數(shù)指定的字符串寫入
 */
outputStreamWriter1.write(68);
outputStreamWriter1.write("jshgh");
outputStreamWriter1.write('j');

/**
 * 2. 刷新流
 */
outputStreamWriter1.flush();

/**
 * 3. 關(guān)閉流
 */
outputStreamWriter1.close();
  • 總結(jié)

17.4.12 InputStreamReader類(重點)

  • 作用

java.io.InputStreamReader類主要用于實現(xiàn)從字節(jié)流到字符流的轉(zhuǎn)換激况。

  • 常用方法
方法聲明 功能介紹
InputStreamReader(InputStream in) 根據(jù)參數(shù)指定的引用來構(gòu)造對象
InputStreamReader(InputStream in, String charsetName) 根據(jù)參數(shù)指定的引用和編碼來構(gòu)造對象
int read(char[] cbuf) 讀取字符數(shù)據(jù)到參數(shù)指定的數(shù)組
void close() 用于關(guān)閉輸出流并釋放有關(guān)的資源

17.4.13 字符編碼

  • 背景

    • 計算機只能識別二進制數(shù)據(jù)作彤,早期就是電信號。為了方便計算機可以識別各個國家的文字乌逐,就需要
      將各個國家的文字采用數(shù)字編號的方式進行描述并建立對應(yīng)的關(guān)系表宦棺,該表就叫做編碼表。
  • 常見編碼

    • GBK

    • UTF-8

    • ASCII

  • 發(fā)展

17.4.14 DataOutputStream類(了解)

  • 作用

java.io.DataOutputStream類主要用于以適當(dāng)?shù)姆绞綄⒒緮?shù)據(jù)類型寫入輸出流中黔帕。

  • 常用方法

代碼demo

DataOutputStream dataOutputStream = null;

try {
    dataOutputStream = new DataOutputStream(new FileOutputStream("e:/myFile.txt"));

    System.out.println("-------------------常用方法---------------------");

    /**
     * 1. 用于將參數(shù)指定的整數(shù)一次性寫入輸出流代咸,優(yōu)先寫入高字節(jié)
     */
    dataOutputStream.writeInt(67);             //   C
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (null != dataOutputStream) {
        try {
            dataOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

17.4.14 DataInputStream類(了解)

  • 作用

java.io.DataInputStream類主要用于以適當(dāng)?shù)姆绞綇妮斎肓髦凶x取基本數(shù)據(jù)類型的數(shù)據(jù)。

  • 常用方法
DataInputStream dis = null;

try {
    // 1.創(chuàng)建DataInputStream類型的對象與d:/a.txt文件關(guān)聯(lián)
    dis = new DataInputStream(new FileInputStream("e:/myFile.txt"));
    // 2.從輸入流中讀取一個整數(shù)并打印
    int res = dis.readInt(); // 讀取4個字節(jié)
    //int res = dis.read();      // 讀取1個字節(jié)
    System.out.println("讀取到的整數(shù)數(shù)據(jù)是:" + res); // 67
} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 3.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != dis) {
        try {
            dis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

17.4.15 序列化與反序列化

  • 基本概念

    • 序列化 (對象 -> 字節(jié)流)

    • 反序列化 (字節(jié)流 -> 對象)

  • 序列化版本號

    在 序列化存儲/反序列化讀取 或者是 序列化傳輸/反序列化接收 時成黄,JVM 會把傳來的字節(jié)流中的serialVersionUID與本地相應(yīng)實體(類)的serialVersionUID進行比較呐芥,如果相同就認(rèn)為是一致的,可以進行反序列化奋岁,否則就會出現(xiàn)序列化版本不一致的異常思瘟。

  • transient關(guān)鍵字

    在Java中,當(dāng)一個類實現(xiàn)了java.io.Serializable接口闻伶,即表明了該類可以被序列化滨攻。我們可以把該類的屬性序列化然后保存在外部,或者跟另外一個jvm進行數(shù)據(jù)傳遞蓝翰。但是光绕,我們是否想過,如果一個類包含隱私信息畜份,如用戶的密碼等诞帐,那么這個屬性就不能夠被序列化到外部。當(dāng)然爆雹,我們可以在序列化之前手動set該值為null停蕉,但是最優(yōu)雅的做法就是使用transient關(guān)鍵字愕鼓。

17.4.16 ObjectOutputStream類(重點)

  • 作用

    • java.io.ObjectOutputStream類主要用于將一個對象的所有內(nèi)容整體寫入到輸出流中。

    • 只能將支持 java.io.Serializable 接口的對象寫入流中慧起。

    • 類通過實現(xiàn) java.io.Serializable 接口以啟用其序列化功能菇晃。

    • 所謂序列化主要指將一個對象需要存儲的相關(guān)信息有效組織成字節(jié)序列的轉(zhuǎn)化過程。

  • 常用方法

ObjectOutputStream oos = null;

try {
    // 1.創(chuàng)建ObjectOutputStream類型的對象與d:/a.txt文件關(guān)聯(lián)
    oos = new ObjectOutputStream(new FileOutputStream("e:/myFile.txt"));
    // 2.準(zhǔn)備一個Student類型的對象并初始化
    Student student = new Student("fuyi", "123456");
    // 3.將整個Student類型的對象寫入輸出流
    oos.writeObject(student);
    System.out.println("寫入對象成功蚓挤!");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 4.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != oos) {
        try {
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

17.4.17 ObjectInputStream類(重點)

  • 作用

    java.io.ObjectInputStream類主要用于從輸入流中一次性將對象整體讀取出來磺送。

  • 常用方法

ObjectInputStream ois = null;

try {
    // 1.創(chuàng)建ObjectInputStream類型的對象與d:/a.txt文件關(guān)聯(lián)
    ois = new ObjectInputStream(new FileInputStream("e:/myFile.txt"));
    // 2.從輸入流中讀取一個對象并打印
    Object obj = ois.readObject();
    System.out.println("讀取到的對象是:" + obj); // fuyi 123456
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} finally {
    // 3.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != ois) {
        try {
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 編程開發(fā)經(jīng)驗

    當(dāng)希望將多個對象寫入文件時,通常建議將多個對象放入一個集合中屈尼,然后將集合這個整體看做一
    個對象寫入輸出流中册着,此時只需要調(diào)用一次readObject方法就可以將整個集合的數(shù)據(jù)讀取出來,
    從而避免了通過返回值進行是否達到文件末尾的判斷脾歧。

17.4.18 RandomAccessFile類

  • 作用

    java.io.RandomAccessFile類主要支持對隨機訪問文件的讀寫操作甲捏。

  • 常用方法

方法聲明 功能介紹
RandomAccessFile(String name, String mode) 根據(jù)參數(shù)指定的名稱和模式構(gòu)造對象 r: 以只讀方式打開 rw:打開以便讀取和寫入 rwd:打開以便讀取和寫入,同步文件內(nèi)容的更新 rws:打開以便讀取和寫入鞭执,同步文件內(nèi)容和元數(shù)據(jù)的更新
int read() 讀取單個字節(jié)的數(shù)據(jù)
void seek(long pos) 用于設(shè)置從此文件的開頭開始測量的文件指針偏移量
void write(int b) 將參數(shù)指定的單個字節(jié)寫入
void close() 用于關(guān)閉流并釋放有關(guān)的資源
  • 代碼demo
RandomAccessFile raf = null;

try {
    // 1.創(chuàng)建RandomAccessFile類型的對象與d:/a.txt文件關(guān)聯(lián)
    raf = new RandomAccessFile("e:/myFile.txt", "rw");
    // 2.對文件內(nèi)容進行隨機讀寫操作
    // 設(shè)置距離文件開頭位置的偏移量司顿,從文件開頭位置向后偏移3個字節(jié)    aellhello
    raf.seek(3);
    int res = raf.read();
    System.out.println("讀取到的單個字符是:" + (char)res); // a l
    res = raf.read();
    System.out.println("讀取到的單個字符是:" + (char)res); // h 指向了e
    raf.write('2'); // 執(zhí)行該行代碼后覆蓋了字符'e'
    System.out.println("寫入數(shù)據(jù)成功!");
      
} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 3.關(guān)閉流對象并釋放有關(guān)的資源
    if (null != raf) {
        try {
            raf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

第十八章 多線程

18.1 基本概念

18.1.1 程序和進程

  • 程序

    數(shù)據(jù)結(jié)構(gòu) + 算法兄纺,主要指存放在硬盤上的可執(zhí)行文件大溜。

  • 進程

    主要指運行在內(nèi)存中的可執(zhí)行文件。

  • 目前主流的操作系統(tǒng)都支持多進程估脆,為了讓操作系統(tǒng)同時可以執(zhí)行多個任務(wù)钦奋,但進程是重量級的,
    也就是新建一個進程會消耗CPU和內(nèi)存空間等系統(tǒng)資源疙赠,因此進程的數(shù)量比較局限付材。

18.1.2 線程

  • 為了解決上述問題就提出線程的概念,線程就是進程內(nèi)部的程序流圃阳,也就是說操作系統(tǒng)內(nèi)部支持多
    進程的厌衔,而每個進程的內(nèi)部又是支持多線程的,線程是輕量的捍岳,新建線程會共享所在進程的系統(tǒng)資
    源富寿,因此目前主流的開發(fā)都是采用多線程。

  • 多線程是采用時間片輪轉(zhuǎn)法來保證多個線程的并發(fā)執(zhí)行锣夹,所謂并發(fā)就是指宏觀并行微觀串行的機
    制页徐,本質(zhì)上還是串行的,只不過是先CPU切換線程的速度很快晕城,所以看起來是并行執(zhí)行泞坦。

18.2 線程的創(chuàng)建(無比重要)

18.2.1 Thread類的概念

  • java.lang.Thread類代表線程,任何線程對象都是Thread類(子類)的實例贰锁。

  • Thread類是線程的模板,封裝了復(fù)雜的線程開啟等操作览闰,封裝了操作系統(tǒng)的差異性。

18.2.2 創(chuàng)建方式

  • 自定義類繼承Thread類并重寫run方法,然后創(chuàng)建該類的對象調(diào)用start方法。

代碼demo

class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
         }
     }

啟動線程

public class test {
    public static void main(String[] args){
      PrimeThread p = new PrimeThread(143);
      p.start();
    }
}

  • 自定義類實現(xiàn)Runnable接口并重寫run方法蟹腾,創(chuàng)建該類的對象作為實參來構(gòu)造Thread類型的對
    象,然后使用Thread類型的對象調(diào)用start方法。

代碼demo

class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
         }
     }

啟動線程

public class test {
    public static void main(String[] args){
       PrimeRun p = new PrimeRun(143);
       new Thread(p).start();
    }
}

18.2.3 常用方法

方法聲明 功能介紹
Thread() 使用無參的方式構(gòu)造對象
Thread(String name) 根據(jù)參數(shù)指定的名稱來構(gòu)造對象
Thread(Runnable target) 根據(jù)參數(shù)指定的引用來構(gòu)造對象螟炫,其中Runnable是個接口類型
Thread(Runnable target,String name) 根據(jù)參數(shù)指定引用和名稱來構(gòu)造對象
void run() 若使用Runnable引用構(gòu)造了線程對象然评,調(diào)用該方法時最終調(diào)用接口中的版本若沒有使用Runnable引用構(gòu)造線程對象,調(diào)用該方法時則啥也不做
void start() 用于啟動線程纳像,Java虛擬機會自動調(diào)用該線程的run方法

代碼demo

/**
 * 測試Thread的無參構(gòu)造方法的所創(chuàng)建的對象調(diào)用run()方法是否是啥也沒干
 *
 * Thread源碼分析
 * 首先new Thread()進入無參構(gòu)造方法:
 * -> 1. init(null, null, "Thread-" + nextThreadNum(), 0);
 * -> 2. private void init(ThreadGroup g, Runnable target, String name,
 *                       long stackSize) {
 *         init(g, target, name, stackSize, null, true);
 *     }
 * -> 3. 在init方法中因為我們傳入的target = null, 又因為在init的方法中this.target = target;所以此時的target == null
 */
Thread thread = new Thread();

/**
 * run()方法源碼:
 * -> 4. if (target != null) {
 *             target.run();
 *         }
 * -> 結(jié)論:沒有執(zhí)行run()方法
 */
thread.run();
System.out.println("測試結(jié)果L妒蕖!");

測試run()和start()方法

public class SubThreadTest extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("SubThreadTeat子線程打印" + i);
        }
    }
}

代碼測試

/**
 * 測試線程構(gòu)造方法一的啟動
 */
//1. 創(chuàng)建一個Thread父類的引用指向子類SubThreadTest的對象
Thread thread1 = new SubThreadTest();

//2. run()
//注意:調(diào)用run()方法其實并沒有啟動一個子線程铸本,只不過是執(zhí)行SubThreadTest類中的run()锡足,還是又主線程main進行執(zhí)行指令
thread1.run();

//真正啟動一條線程,本質(zhì)是JVM會去啟動一條線程,用來執(zhí)行SubThreadTest類中的run()方法代碼
thread1.start();

//3. 主線程main方法中打印
for (int i = 0; i < 10; i++) {
    System.out.println("主線程main打幽グ:" + i);
}

線程構(gòu)造方法二

public class SubRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("SubRunnable子線程打印" + i);
        }
    }
}

測試運行

SubRunnable subRunnable = new SubRunnable();

/**
 * 由Thread源碼可得target = subRunnable
 */
Thread thread = new Thread(subRunnable);

/**
 * if (target != null) {
 *             target.run();
 *         }
 * 而此時的target = subRunnable, 所以調(diào)用的是SubRunnable.run()方法
 */
thread.start();
for (int i = 0; i < 10; i++) {
    System.out.println("主線程main打印" + i);
}

18.2.4 執(zhí)行流程

  • 執(zhí)行main方法的線程叫做主線程设预,執(zhí)行run方法的線程叫做新線程/子線程宾符。

  • main方法是程序的入口哄褒,對于start方法之前的代碼來說链嘀,由主線程執(zhí)行一次,當(dāng)start方法調(diào)用成功后線程的個數(shù)由1個變成了2個,新啟動的線程去執(zhí)行run方法的代碼熄驼,主線程繼續(xù)向下執(zhí)行筷笨,兩個線程各自獨立運行互不影響。

  • 當(dāng)run方法執(zhí)行完畢后子線程結(jié)束审胸,當(dāng)main方法執(zhí)行完畢后主線程結(jié)束映企。

  • 兩個線程執(zhí)行沒有明確的先后執(zhí)行次序,由操作系統(tǒng)調(diào)度算法來決定焚挠。

18.2.5 方式比較

18.2.6 匿名內(nèi)部類方式

實現(xiàn)兩種線程創(chuàng)建的代碼編寫

/**
 * 1. 原始語法
 */
// 繼承Thread類的方式
Thread thread = new Thread() {
    @Override
    public void run() {
        System.out.println("匿名方式創(chuàng)建");
    }
};
thread.start();

// 實現(xiàn)Runnable接口的方式
Runnable ra = new Runnable() {
    @Override
    public void run() {
        System.out.println("匿名方式創(chuàng)建");
    }
};
Thread thread1 = new Thread(ra);
thread1.start();

/**
 * 2. JDK8的lambda語法
 */
new Thread(() -> System.out.println("lambda匿名方式創(chuàng)建")).start();

18.3 線程的聲明周期

18.4 線程的編號和名稱

方法聲明 功能介紹
long getId() 獲取調(diào)用對象所表示線程的編號
String getName() 獲取調(diào)用對象所表示線程的名稱
void setName(String name) 設(shè)置/修改線程的名稱為參數(shù)指定的數(shù)值
static Thread currentThread() 獲取當(dāng)前正在執(zhí)行線程的引用

代碼示例

public class ThreadIdNameTest extends Thread{

public ThreadIdNameTest(String name) {
    super(name);
}

public ThreadIdNameTest() {

}

/**
 * 測試對線程id和name的管理
 */
@Override
public void run() {
    System.out.println("子線程的信息:");
    System.out.println("子線程的名字:" + getName());
    System.out.println("子線程的Id:" + getId());
}

public static void main(String[] args) {

    /**
     * 結(jié)果打印
     * 子線程的名字:Thread-0
     * 子線程的Id:12
     */
    Thread thread = new ThreadIdNameTest();
    thread.start();

    /**
     * 修改線程名 fuyi
     * 子線程的名字:fuyi
     * 子線程的Id:13
     */
    ThreadIdNameTest thread2 = new ThreadIdNameTest("fuyi");
    thread2.start();

    /**
     * 獲取當(dāng)前主線程
     * 主線程名字為:main
     * 主線程ID為:1
     */
    Thread thread1 = Thread.currentThread();
    System.out.println("主線程名字為:" + thread1.getName());
    System.out.println("主線程ID為:" + thread1.getId());
}
}

實現(xiàn)接口的方式

public class RunnableIdNameTest implements Runnable {

    @Override
    public void run() {
        // 獲取當(dāng)前子線程名字
        Thread thread = Thread.currentThread();
        System.out.println("子線程的名字為:" + thread.getName());
        System.out.println("子線程的ID為:" + thread.getId());
    }

    public static void main(String[] args) {

        /**
         * 無參方式創(chuàng)建啟動線程
         * 結(jié)果打优鹕怼:
         * 子線程的名字為:Thread-0
         * 子線程的ID為:12
         */
        new Thread(new RunnableIdNameTest()).start();

        /**
         * 設(shè)置線程名構(gòu)造
         * 結(jié)果打印
         * 子線程的名字為:fuyi
         * 子線程的ID為:13
         */
        new Thread(new RunnableIdNameTest(),"fuyi").start();

        System.out.println("主線程" + Thread.currentThread().getName());
    }
}

18.5 常用方法

方法聲明 功能介紹
static void yield() 當(dāng)前線程讓出處理器(離開Running狀態(tài))跪另,使當(dāng)前線程進入Runnable狀態(tài)等待
static void sleep(times) 使當(dāng)前線程從 Running 放棄處理器進入Block狀態(tài), 休眠times毫秒, 再返回到Runnable如果其他線程打斷當(dāng)前線程的Block(sleep), 就會發(fā)生InterruptedException。
int getPriority() 獲取線程的優(yōu)先級void setPriority(int newPriority)修改線程的優(yōu)先級彤枢。優(yōu)先級越高的線程不一定先執(zhí)行狰晚,但該線程獲取到時間片的機會會更多一些
void join() 等待該線程終止
void join(long millis) 等待參數(shù)指定的毫秒數(shù)
boolean isDaemon() 用于判斷是否為守護線程
void setDaemon(boolean on) 用于設(shè)置線程為守護線程

18.6 線程同步機制(重點)

18.6.1 背景

  • 當(dāng)多個線程同時訪問同一種共享資源時,可能會造成數(shù)據(jù)的覆蓋等不一致性問題缴啡,此時就需要對線程之間進行通信和協(xié)調(diào)壁晒,該機制就叫做線程的同步機制。
  • 多個線程并發(fā)讀寫同一個臨界資源時會發(fā)生線程并發(fā)安全問題业栅。
  • 異步操作:多線程并發(fā)的操作秒咐,各自獨立運行。
  • 同步操作:多線程串行的操作碘裕,先后執(zhí)行的順序携取。

18.6.2 解決方案

  • 由程序結(jié)果可知:當(dāng)兩個線程同時對同一個賬戶進行取款時,導(dǎo)致最終的賬戶余額不合理帮孔。
  • 引發(fā)原因:線程一執(zhí)行取款時還沒來得及將取款后的余額寫入后臺雷滋,線程二就已經(jīng)開始取款。
  • 解決方案:讓線程一執(zhí)行完畢取款操作后文兢,再讓線程二執(zhí)行即可晤斩,將線程的并發(fā)操作改為串行操作。
  • 經(jīng)驗分享:在以后的開發(fā)盡量減少串行操作的范圍姆坚,從而提高效率澳泵。

18.6.3 實現(xiàn)方式

  • 在Java語言中使用synchronized關(guān)鍵字來實現(xiàn)同步/對象鎖機制從而保證線程執(zhí)行的原子性,具體
    方式如下:
    使用同步代碼塊的方式實現(xiàn)部分代碼的鎖定兼呵,格式如下:
    synchronized(類類型的引用) {
    編寫所有需要鎖定的代碼兔辅;
    }
  • 使用同步方法的方式實現(xiàn)所有代碼的鎖定。
    直接使用synchronized關(guān)鍵字來修飾整個方法即可
    該方式等價于:
    synchronized(this) { 整個方法體的代碼 }

18.6.4 靜態(tài)方法鎖定

  • 當(dāng)我們對一個靜態(tài)方法加鎖击喂,如:
    public synchronized static void xxx(){….}
  • 那么該方法鎖的對象是類對象维苔。每個類都有唯一的一個類對象。獲取類對象的方式:類名.class茫负。
  • 靜態(tài)方法與非靜態(tài)方法同時使用了synchronized后它們之間是非互斥關(guān)系的蕉鸳。
  • 原因在于:靜態(tài)方法鎖的是類對象而非靜態(tài)方法鎖的是當(dāng)前方法所屬對象。

18.6.5 注意事項

  • 使用synchronized保證線程同步應(yīng)當(dāng)注意:
    • 多個需要同步的線程在訪問同步塊時忍法,看到的應(yīng)該是同一個鎖對象引用潮尝。
    • 在使用同步塊時應(yīng)當(dāng)盡量減少同步范圍以提高并發(fā)的執(zhí)行效率。

18.6.6 線程安全和不安全類

  • StringBuffer類是線程安全的類饿序,但StringBuilder類不是線程安全的類勉失。
  • Vector類和 Hashtable類是線程安全的類,但ArrayList類和HashMap類不是線程安全的類原探。
  • Collections.synchronizedList() 和 Collections.synchronizedMap()等方法實現(xiàn)安全乱凿。

18.6.7 死鎖

  • 線程一執(zhí)行的代碼:
    public void run(){
    synchronized(a){ //持有對象鎖a顽素,等待對象鎖b
    synchronized(b){
    編寫鎖定的代碼;
    }
    }
    }
  • 線程二執(zhí)行的代碼:
    public void run(){
    synchronized(b){ //持有對象鎖b,等待對象鎖a
    synchronized(a){
    編寫鎖定的代碼;
    }
    }
    }
  • 注意:
    在以后的開發(fā)中盡量減少同步的資源徒蟆,減少同步代碼塊的嵌套結(jié)構(gòu)的使用胁出!

18.6.8 使用鎖實現(xiàn)線程同步

  • 基本概念

    • 從Java5開始提供了更強大的線程同步機制—使用顯式定義的同步鎖對象來實現(xiàn)。
    • java.util.concurrent.locks.Lock接口是控制多個線程對共享資源進行訪問的工具段审。
    • 該接口的主要實現(xiàn)類是ReentrantLock類全蝶,該類擁有與synchronized相同的并發(fā)性,在以后的線程
      安全控制中寺枉,經(jīng)常使用ReentrantLock類顯式加鎖和釋放鎖抑淫。
  • 常用方法

方法聲明 功能介紹
ReentrantLock() 使用無參方式構(gòu)造對象
void lock() 獲取鎖
void unlock() 釋放鎖
  • 與synchronized方式的比較

    • Lock是顯式鎖,需要手動實現(xiàn)開啟和關(guān)閉操作姥闪,而synchronized是隱式鎖始苇,執(zhí)行鎖定代碼后自動
      釋放。

    • Lock只有同步代碼塊方式的鎖筐喳,而synchronized有同步代碼塊方式和同步方法兩種鎖催式。

    • 使用Lock鎖方式時,Java虛擬機將花費較少的時間來調(diào)度線程疏唾,因此性能更好蓄氧。

18.6.9 Object類常用方法

方法聲明 功能介紹
void wait() 用于使得線程進入等待狀態(tài),直到其它線程調(diào)用notify()或notifyAll()方法
void wait(long timeout) 用于進入等待狀態(tài)槐脏,直到其它線程調(diào)用方法或參數(shù)指定的毫秒數(shù)已經(jīng)過去為止
void notify() 用于喚醒等待的單個線程
void notifyAll() 用于喚醒等待的所有線程

18.6.10 線程池

  • 實現(xiàn)Callable接口

  • 從Java5開始新增加創(chuàng)建線程的第三種方式為實現(xiàn)java.util.concurrent.Callable接口。

  • 常用的方法如下:

方法聲明 功能介紹
V call() 計算結(jié)果并返回
  • FutureTask類
    -java.util.concurrent.FutureTask類用于描述可取消的異步計算瘾英,該類提供了Future接口的基本實
    現(xiàn)懈贺,包括啟動和取消計算蜻韭、查詢計算是否完成以及檢索計算結(jié)果的方法,也可以用于獲取方法調(diào)用
    后的返回結(jié)果牌废。
  • 常用的方法如下:
方法聲明 功能介紹
FutureTask(Callable callable) 根據(jù)參數(shù)指定的引用來創(chuàng)建一個未來任務(wù)
V get() 獲取call方法計算的結(jié)果
  • 線程池的由來
    在服務(wù)器編程模型的原理,每一個客戶端連接用一個單獨的線程為之服務(wù)啤握,當(dāng)與客戶端的會話結(jié)束
    時鸟缕,線程也就結(jié)束了,即每來一個客戶端連接排抬,服務(wù)器端就要創(chuàng)建一個新線程懂从。
    如果訪問服務(wù)器的客戶端很多,那么服務(wù)器要不斷地創(chuàng)建和銷毀線程蹲蒲,這將嚴(yán)重影響服務(wù)器的性
    能番甩。

  • 概念和原理
    線程池的概念:首先創(chuàng)建一些線程,它們的集合稱為線程池届搁,當(dāng)服務(wù)器接受到一個客戶請求后缘薛,就
    從線程池中取出一個空閑的線程為之服務(wù)窍育,服務(wù)完后不關(guān)閉該線程,而是將該線程還回到線程池
    中宴胧。
    在線程池的編程模式下漱抓,任務(wù)是提交給整個線程池,而不是直接交給某個線程恕齐,線程池在拿到任務(wù)
    后乞娄,它就在內(nèi)部找有無空閑的線程,再把任務(wù)交給內(nèi)部某個空閑的線程檐迟,任務(wù)是提交給整個線程
    池补胚,一個線程同時只能執(zhí)行一個任務(wù),但可以同時向一個線程池提交多個任務(wù)追迟。

  • 相關(guān)類和方法
    從Java5開始提供了線程池的相關(guān)類和接口:java.util.concurrent.Executors類和
    java.util.concurrent.ExecutorService接口溶其。

    方法聲明 功能介紹
    static ExecutorService newCachedThreadPool() 創(chuàng)建一個可根據(jù)需要創(chuàng)建新線程的線程池
    static ExecutorService newFixedThreadPool(int nThreads) 創(chuàng)建一個可重用固定線程數(shù)的線程池
    static ExecutorService newSingleThreadExecutor() 創(chuàng)建一個只有一個線程的線程池
  • 其中Executors是個工具類和線程池的工廠類,可以創(chuàng)建并返回不同類型的線程池敦间,常用方法如下:

    方法聲明 功能介紹
    void execute(Runnable command) 執(zhí)行任務(wù)和命令瓶逃,通常用于執(zhí)行Runnable
    Future submit(Callable task) 執(zhí)行任務(wù)和命令,通常用于執(zhí)行Callable
    void shutdown() 啟動有序關(guān)閉

第十九章 網(wǎng)絡(luò)編程

19.1.1 七層網(wǎng)絡(luò)模型

OSI(Open System Interconnect)廓块,即開放式系統(tǒng)互聯(lián)厢绝,是ISO(國際標(biāo)準(zhǔn)化組織)組織在1985
年研究的網(wǎng)絡(luò)互連模型。

OSI七層模型和TCP/IP五層模型的劃分如下:

當(dāng)發(fā)送數(shù)據(jù)時带猴,需要對發(fā)送的內(nèi)容按照上述七層模型進行層層加包后發(fā)送出去昔汉。

當(dāng)接收數(shù)據(jù)時,需要對接收的內(nèi)容按照上述七層模型相反的次序?qū)訉硬鸢@示出來拴清。

19.1.2 相關(guān)的協(xié)議(筆試題)

(1)協(xié)議的概念

  • 計算機在網(wǎng)絡(luò)中實現(xiàn)通信就必須有一些約定或者規(guī)則靶病,這種約定和規(guī)則就叫做通信協(xié)議,通信協(xié)議
    可以對速率口予、傳輸代碼娄周、代碼結(jié)構(gòu)、傳輸控制步驟沪停、出錯控制等制定統(tǒng)一的標(biāo)準(zhǔn)煤辨。

(2)TCP協(xié)議

  • 傳輸控制協(xié)議(Transmission Control Protocol),是一種面向連接的協(xié)議木张,類似于打電話众辨。
    • 建立連接 => 進行通信 => 斷開連接
    • 在傳輸前采用"三次握手"方式。
    • 在通信的整個過程中全程保持連接窟哺,形成數(shù)據(jù)傳輸通道泻轰。
    • 保證了數(shù)據(jù)傳輸?shù)目煽啃院陀行蛐浴?/li>
    • 是一種全雙工的字節(jié)流通信方式,可以進行大數(shù)據(jù)量的傳輸且轨。
    • 傳輸完畢后需要釋放已建立的連接浮声,發(fā)送數(shù)據(jù)的效率比較低虚婿。
      (3)UDP協(xié)議
  • 用戶數(shù)據(jù)報協(xié)議(User Datagram Protocol),是一種非面向連接的協(xié)議泳挥,類似于寫信然痊。
    • 在通信的整個過程中不需要保持連接,其實是不需要建立連接屉符。
    • 不保證數(shù)據(jù)傳輸?shù)目煽啃院陀行蛐浴?/li>
    • 是一種全雙工的數(shù)據(jù)報通信方式剧浸,每個數(shù)據(jù)報的大小限制在64K內(nèi)。
    • 發(fā)送數(shù)據(jù)完畢后無需釋放資源矗钟,開銷小唆香,發(fā)送數(shù)據(jù)的效率比較高,速度快吨艇。

19.1.3 IP地址(重點)

  • 192.168.1.1 - 是絕大多數(shù)路由器的登錄地址躬它,主要配置用戶名和密碼以及Mac過濾。

  • IP地址是互聯(lián)網(wǎng)中的唯一地址標(biāo)識东涡,本質(zhì)上是由32位二進制組成的整數(shù)冯吓,叫做IPv4,當(dāng)然也有128位二進制組成的整數(shù)疮跑,叫做IPv6组贺,目前主流的還是IPv4。

  • 日常生活中采用點分十進制表示法來進行IP地址的描述祖娘,將每個字節(jié)的二進制轉(zhuǎn)化為一個十進制整數(shù)失尖,不同的整數(shù)之間采用小數(shù)點隔開。如:
    0x01020304 => 1.2.3.4

  • 查看IP地址的方式:

    Windows系統(tǒng):在dos窗口中使用ipconfig或ipconfig/all命令即可

    Unix/linux系統(tǒng):在終端窗口中使用ifconfig或/sbin/ifconfig命令即可

特殊的地址

本地回環(huán)地址(hostAddress):127.0.0.1 主機名(hostName):localhost

19.1.4 端口號(重點)

  • IP地址 - 可以定位到具體某一臺設(shè)備渐苏。

  • 端口號 - 可以定位到該設(shè)備中具體某一個進程雹仿。

  • 端口號本質(zhì)上是16位二進制組成的整數(shù),表示范圍是:0 ~ 65535整以,其中0 ~ 1024之間的端口號通
    常被系統(tǒng)占用,建議編程從1025開始使用峻仇。

  • 特殊的端口:
    HTTP:80 FTP:21 Oracle:1521 MySQL:3306 Tomcat:8080

  • 網(wǎng)絡(luò)編程需要提供:IP地址 + 端口號公黑,組合在一起叫做網(wǎng)絡(luò)套接字:Socket。

19.2 基于tcp協(xié)議的編程模型(重點)

19.2.1 C/S架構(gòu)的簡介

  • 在C/S模式下客戶向服務(wù)器發(fā)出服務(wù)請求摄咆,服務(wù)器接收請求后提供服務(wù)凡蚜。

  • 例如:在一個酒店中,顧客找服務(wù)員點菜,服務(wù)員把點菜單通知廚師吭从,廚師按點菜單做好菜后讓服
    務(wù)員端給客戶朝蜘,這就是一種C/S工作方式。如果把酒店看作一個系統(tǒng)涩金,服務(wù)員就是客戶端谱醇,廚師就
    是服務(wù)器暇仲。這種系統(tǒng)分工和協(xié)同工作的方式就是C/S的工作方式。

  • 客戶端部分:為每個用戶所專有的副渴,負(fù)責(zé)執(zhí)行前臺功能奈附。

  • 服務(wù)器部分:由多個用戶共享的信息與功能,招待后臺服務(wù)煮剧。

19.2.2 編程模型

服務(wù)器:
(1)創(chuàng)建ServerSocket類型的對象并提供端口號斥滤;
(2)等待客戶端的連接請求,調(diào)用accept()方法勉盅;
(3)使用輸入輸出流進行通信佑颇;
(4)關(guān)閉Socket;
客戶端:
(1)創(chuàng)建Socket類型的對象并提供服務(wù)器的IP地址和端口號草娜;
(2)使用輸入輸出流進行通信挑胸;
(3)關(guān)閉Socket;

19.2.3 相關(guān)類和方法的解析

(1)ServerSocket類
java.net.ServerSocket類主要用于描述服務(wù)器套接字信息(大插排)驱还。

  • 常用的方法如下:
方法聲明 功能介紹
ServerSocket(int port) 根據(jù)參數(shù)指定的端口號來構(gòu)造對象
Socket accept() 偵聽并接收到此套接字的連接請求
void close() 用于關(guān)閉套接字

(2)Socket類
java.net.Socket類主要用于描述客戶端套接字嗜暴,是兩臺機器間通信的端點(小插排)。

  • 常用的方法如下:
方法聲明 功能介紹
Socket(String host, int port) 根據(jù)指定主機名和端口來構(gòu)造對象
InputStream getInputStream() 用于獲取當(dāng)前套接字的輸入流
OutputStream getOutputStream() 用于獲取當(dāng)前套接字的輸出流
void close() 用于關(guān)閉套接字

(3)注意事項
客戶端 Socket 與服務(wù)器端 Socket 對應(yīng), 都包含輸入和輸出流议蟆。
客戶端的socket.getInputStream() 連接于服務(wù)器socket.getOutputStream()闷沥。
客戶端的socket.getOutputStream()連接于服務(wù)器socket.getInputStream()

19.3 基于udp協(xié)議的編程模型(熟悉)

19.3.1 編程模型

接收方:

(1)創(chuàng)建DatagramSocket類型的對象并提供端口號;

(2)創(chuàng)建DatagramPacket類型的對象并提供緩沖區(qū)咐容;

(3)通過Socket接收數(shù)據(jù)內(nèi)容存放到Packet中舆逃,調(diào)用receive方法;

(4)關(guān)閉Socket戳粒;

發(fā)送方:
(1)創(chuàng)建DatagramSocket類型的對象路狮;

(2)創(chuàng)建DatagramPacket類型的對象并提供接收方的通信地址;

(3)通過Socket將Packet中的數(shù)據(jù)內(nèi)容發(fā)送出去蔚约,調(diào)用send方法奄妨;

(4)關(guān)閉Socket;

19.3.2 相關(guān)類和方法的解析

(1)DatagramSocket類
java.net.DatagramSocket類主要用于描述發(fā)送和接收數(shù)據(jù)報的套接字(郵局)苹祟。
換句話說砸抛,該類就是包裹投遞服務(wù)的發(fā)送或接收點。

  • 常用的方法如下:
方法聲明 功能介紹
DatagramSocket() 使用無參的方式構(gòu)造對象
DatagramSocket(int port) 根據(jù)參數(shù)指定的端口號來構(gòu)造對象
void receive(DatagramPacket p) 用于接收數(shù)據(jù)報存放到參數(shù)指定的位置
void send(DatagramPacket p) 用于將參數(shù)指定的數(shù)據(jù)報發(fā)送出去
void close() 關(guān)閉Socket并釋放相關(guān)資源

(2)DatagramPacket類
java.net.DatagramPacket類主要用于描述數(shù)據(jù)報树枫,數(shù)據(jù)報用來實現(xiàn)無連接包裹投遞服務(wù)直焙。

  • 常用的方法如下:
方法聲明 功能介紹
DatagramPacket(byte[] buf, int length) 根據(jù)參數(shù)指定的數(shù)組來構(gòu)造對象,用于接收長度為length的數(shù)據(jù)報
DatagramPacket(byte[] buf, int length,InetAddress address, int port) 根據(jù)參數(shù)指定數(shù)組來構(gòu)造對象砂轻,將數(shù)據(jù)報發(fā)送到指定地址和端口
InetAddress getAddress() 用于獲取發(fā)送方或接收方的通信地址
int getPort() 用于獲取發(fā)送方或接收方的端口號
int getLength() 用于獲取發(fā)送數(shù)據(jù)或接收數(shù)據(jù)的長度

(3)InetAddress類
java.net.InetAddress類主要用于描述互聯(lián)網(wǎng)通信地址信息奔誓。

  • 常用的方法如下:
方法聲明 功能介紹
static InetAddress getLocalHost() 用于獲取當(dāng)前主機的通信地址
static InetAddress getByName(String host) 根據(jù)參數(shù)指定的主機名獲取通信地址

19.4 URL類(熟悉)

19.4.1 基本概念

java.net.URL(Uniform Resource Identifier)類主要用于表示統(tǒng)一的資源定位器,也就是指向萬
維網(wǎng)上“資源”的指針搔涝。這個資源可以是簡單的文件或目錄厨喂,也可以是對復(fù)雜對象的引用和措,例如對數(shù)
據(jù)庫或搜索引擎的查詢等。
通過URL可以訪問萬維網(wǎng)上的網(wǎng)絡(luò)資源杯聚,最常見的就是www和ftp站點臼婆,瀏覽器通過解析給定的
URL可以在網(wǎng)絡(luò)上查找相應(yīng)的資源。
URL的基本結(jié)構(gòu)如下:
<傳輸協(xié)議>://<主機名>:<端口號>/<資源地址>

方法聲明 功能介紹
URL(String spec) 根據(jù)參數(shù)指定的字符串信息構(gòu)造對象
String getProtocol() 獲取協(xié)議名稱
String getHost() 獲取主機名稱
int getPort() 獲取端口號
String getPath() 獲取路徑信息
String getFile() 獲取文件名
URLConnection openConnection() 獲取URLConnection類的實例
方法聲明 功能介紹
InputStream getInputStream() 獲取輸入流
void disconnect() 斷開連接

第二十章 反射機制

20.1 基本概念

通常情況下編寫代碼都是固定的幌绍,無論運行多少次執(zhí)行的結(jié)果也是固定的颁褂,在某些特殊場合中編寫
代碼時不確定要創(chuàng)建什么類型的對象,也不確定要調(diào)用什么樣的方法傀广,這些都希望通過運行時傳遞
的參數(shù)來決定颁独,該機制叫做動態(tài)編程技術(shù),也就是反射機制伪冰。
通俗來說誓酒,反射機制就是用于動態(tài)創(chuàng)建對象并且動態(tài)調(diào)用方法的機制。
目前主流的框架底層都是采用反射機制實現(xiàn)的贮聂。如:

Person p = new Person(); - 表示聲明Person類型的引用指向Person類型的對象
p.show(); - 表示調(diào)用Person類中的成員方法show

20.2 Class類

20.2.1 基本概念

java.lang.Class類的實例可以用于描述Java應(yīng)用程序中的類和接口靠柑,也就是一種數(shù)據(jù)類型。
該類沒有公共構(gòu)造方法吓懈,該類的實例由Java虛擬機和類加載器自動構(gòu)造完成歼冰,本質(zhì)上就是加載到內(nèi)
存中的運行時類。

20.2.2 獲取Class對象的方式

使用數(shù)據(jù)類型.class的方式可以獲取對應(yīng)類型的Class對象(掌握)耻警。

使用引用/對象.getClass()的方式可以獲取對應(yīng)類型的Class對象隔嫡。

使用包裝類.TYPE的方式可以獲取對應(yīng)基本數(shù)據(jù)類型的Class對象。

使用Class.forName()的方式來獲取參數(shù)指定類型的Class對象(掌握)甘穿。

使用類加載器ClassLoader的方式獲取指定類型的Class對象腮恩。

20.2.3 常用的方法(掌握)

方法聲明 功能介紹
static Class<?> forName(String className) 用于獲取參數(shù)指定類型對應(yīng)的Class對象并返回
T newInstance() 用于創(chuàng)建該Class對象所表示類的新實例

20.3 Constructor類

20.3.1 基本概念

java.lang.reflect.Constructor類主要用于描述獲取到的構(gòu)造方法信息

20.3.2 Class類的常用方法

方法聲明 功能介紹
Constructor getConstructor(Class<?>...parameterTypes) 用于獲取此Class對象所表示類型中參數(shù)指定的公共構(gòu)造方法
Constructor<?>[] getConstructors() 用于獲取此Class對象所表示類型中所有的公共構(gòu)造方法

20.3.3 Constructor類的常用方法

方法聲明 功能介紹
T newInstance(Object...initargs) 使用此Constructor對象描述的構(gòu)造方法來構(gòu)造Class對象代表類型的新實例
int getModifiers() 獲取方法的訪問修飾符
String getName() 獲取方法的名稱
Class<?>[] getParameterTypes() 獲取方法所有參數(shù)的類型

20.4 Field類

20.4.1 基本概念

java.lang.reflect.Field類主要用于描述獲取到的單個成員變量信息。

20.4.2 Class類的常用方法

方法聲明 功能介紹
Field getDeclaredField(String name) 用于獲取此Class對象所表示類中參數(shù)指定的單個成員變量信息
Field[] getDeclaredFields() 用于獲取此Class對象所表示類中所有成員變量信息

20.4.3 Field類的常用方法

方法聲明 功能介紹
Object get(Object obj) 獲取參數(shù)對象obj中此Field對象所表示成員變量的數(shù)值
void set(Object obj, Object value) 將參數(shù)對象obj中此Field對象表示成員變量的數(shù)值修改為參數(shù)value的數(shù)值
void setAccessible(boolean flag) 當(dāng)實參傳遞true時温兼,則反射對象在使用時應(yīng)該取消 Java 語言訪問檢查
int getModifiers() 獲取成員變量的訪問修飾符
Class<?> getType() 獲取成員變量的數(shù)據(jù)類型
String getName() 獲取成員變量的名稱

20.5 Method類

20.5.1 基本概念

java.lang.reflect.Method類主要用于描述獲取到的單個成員方法信息秸滴。

20.5.2 Class類的常用方法

方法聲明 功能介紹
Method getMethod(String name,Class<?>... parameterTypes) 用于獲取該Class對象表示類中名字為name參數(shù)為parameterTypes的指定公共成員方法
Method[] getMethods() 用于獲取該Class對象表示類中所有公共成員方法

20.5.3 Method類的常用方法

方法聲明 功能介紹
Object invoke(Object obj,Object... args) 使用對象obj來調(diào)用此Method對象所表示的成員方法,實參傳遞args
int getModifiers() 獲取方法的訪問修飾符
Class<?> getReturnType() 獲取方法的返回值類型
String getName() 獲取方法的名稱
Class<?>[] getParameterTypes() 獲取方法所有參數(shù)的類型
Class<?>[] getExceptionTypes() 獲取方法的異常信息

20.6 獲取其它結(jié)構(gòu)信息

方法聲明 功能介紹
Package getPackage() 獲取所在的包信息
Class<? super T> getSuperclass() 獲取繼承的父類信息
Class<?>[] getInterfaces() 獲取實現(xiàn)的所有接口
Annotation[] getAnnotations() 獲取注解信息
Type[] getGenericInterfaces() 獲取泛型信息
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末募判,一起剝皮案震驚了整個濱河市缸榛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兰伤,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钧排,死亡現(xiàn)場離奇詭異敦腔,居然都是意外死亡,警方通過查閱死者的電腦和手機恨溜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門符衔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來找前,“玉大人,你說我怎么就攤上這事判族√墒ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵形帮,是天一觀的道長槽惫。 經(jīng)常有香客問我,道長辩撑,這世上最難降的妖魔是什么界斜? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮合冀,結(jié)果婚禮上各薇,老公的妹妹穿的比我還像新娘。我一直安慰自己君躺,他們只是感情好峭判,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棕叫,像睡著了一般林螃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谍珊,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天治宣,我揣著相機與錄音,去河邊找鬼砌滞。 笑死侮邀,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贝润。 我是一名探鬼主播绊茧,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼打掘!你這毒婦竟也來了华畏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤尊蚁,失蹤者是張志新(化名)和其女友劉穎亡笑,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體横朋,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡仑乌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晰甚。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡衙传,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厕九,到底是詐尸還是另有隱情蓖捶,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布扁远,位于F島的核電站俊鱼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏穿香。R本人自食惡果不足惜亭引,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望皮获。 院中可真熱鬧焙蚓,春花似錦、人聲如沸洒宝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雁歌。三九已至宏浩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間靠瞎,已是汗流浹背比庄。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乏盐,地道東北人佳窑。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像父能,于是被迫代替她去往敵國和親神凑。 傳聞我的和親對象是個殘疾皇子罕模,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容