JAVA筆記19-25

19.01_異常(異常的概述和分類)

  • A:異常的概述
    • 異常就是Java程序在運行過程中出現(xiàn)的錯誤。
  • B:異常的分類
    • 通過API查看Throwable
    • Error
      • 服務器宕機,數(shù)據(jù)庫崩潰等岔绸,比較嚴重的藕漱,無法控制的。
    • Exception
      • 異常 只要是程序運行沒有得到正常的結果,都屬于異常。
      • int a = 10; int b = sc.nextInt(); int c = a / b; syso(c);
      • int[] array = new int[10000];//椛0空間內(nèi)存不夠40000字節(jié)
        C:異常的繼承體系
    • Throwable
      • Error
      • Exception
        • RuntimeException

19.02_異常(JVM默認是如何處理異常的)

  • A:JVM默認是如何處理異常的
    • main函數(shù)收到這個問題時,有兩種處理方式:
    • a:自己將該問題處理,然后繼續(xù)運行
    • b:自己沒有針對的處理方式,只有交給調用main的jvm來處理
    • jvm有一個默認的異常處理機制,就將該異常進行處理.
    • 并將該異常的名稱,異常的信息.異常出現(xiàn)的位置打印在了控制臺上,同時將程序停止運行
  • B:案例演示
    • JVM默認如何處理異常

19.03_異常(try...catch的方式處理異常1)

  • A:異常處理的兩種方式
    • a:try…catch…finally
      • try catch
      • try catch finally
      • try finally
      • 基本格式: try{
      •           可能出現(xiàn)問題的代碼段【throw語句】;
        
      •       }catch(異常類型1 引用名){ 
        
      •           問題的解決方案拆火; 
        
      •       }catch(異常類型n 引用名){ 
        
      •           問題的解決方案胞皱; 
        
      •       }finally{
        
      •           額外釋放資源;
        
      •       }
        
    • b:throws
  • B:try...catch處理異常的基本格式
    • try…catch…finally
  • C:案例演示
    • try...catch的方式處理1個異常

19.04_異常(try...catch的方式處理異常2)

  • A:案例演示
    • try...catch的方式處理多個異常
    • JDK7以后處理多個異常的方式及注意事項

19.05_異常(編譯期異常和運行期異常的區(qū)別)

  • A:編譯期異常和運行期異常的區(qū)別
    • Java中的異常被分為兩大類:編譯時異常和運行時異常酒贬。

    • 所有的RuntimeException類及其子類的實例被稱為運行時異常考蕾,其他的異常就是編譯時異常

    • 編譯時異常

      • Java程序必須顯示處理[try-catch,throws],否則程序就會發(fā)生錯誤牌里,無法通過編譯
      • 流相關的異常炊邦,就屬于編譯時異常
    • 運行時異常

      • 無需顯示處理[try-catch,throws]限寞,也可以和編譯時異常一樣處理
      • 程序員所犯的錯誤,需要回來修改代碼【越界、空指針】
  • B:案例演示
    • 編譯期異常和運行期異常的區(qū)別

19.06_異常(Throwable的幾個常見方法,了解)

  • A:Throwable的幾個常見方法
    • a:getMessage()
      • 獲取異常信息轧膘,返回字符串。
    • b:toString()
      • 獲取異常類名和異常信息赛惩,返回字符串趁餐。
    • c:printStackTrace()
      • 獲取異常類名和異常信息喷兼,以及異常出現(xiàn)在程序中的位置伍掀。返回值void。
      • JVM默認處理方式
  • B:案例演示
    • Throwable的幾個常見方法的基本使用

19.07_異常(throws的方式處理異常)

  • A:throws的方式處理異常
    • 定義功能方法時偷崩,需要把出現(xiàn)的問題暴露出來讓調用者去處理子姜。
    • 那么就通過throws在方法上標識丰榴。
  • B:注意
    • 運行時異常业簿,拋出后可以不顯式處理【不寫throws】
    • 編譯時異常窖杀,拋出后必須顯式處理【必須要寫throws】
  • C:案例演示
    • 舉例分別演示編譯時異常和運行時異常的拋出
    • setAge(-17)

19.08_異常(throw的概述以及和throws的區(qū)別)

  • A:throw的概述
    • 程序員主動拋出異常
    • 在功能方法內(nèi)部出現(xiàn)某種情況,程序不能繼續(xù)運行,需要進行跳轉時,就用throw把異常對象拋出。
  • B:案例演示
    • 分別演示編譯時異常對象和運行時異常對象的拋出
  • C:throws和throw的區(qū)別
    • a:throws
      • 用在方法聲明后面,跟的是異常類名
      • 可以跟多個異常類名,用逗號隔開
      • 表示拋出異常,由該方法的調用者來處理
    • b:throw
      • 用在方法體內(nèi)宗雇,跟的是異常對象名
      • 只能拋出一個異常對象名
      • 表示拋出異常昂芜,由方法體內(nèi)的語句處理

19.09_異常(finally關鍵字的特點及作用)

  • A:finally的特點
    • 被finally控制的語句體一定會執(zhí)行
    • 唯一的特殊情況:在執(zhí)行到finally之前jvm退出了(比如System.exit(0))
  • B:finally的作用
    • 用于釋放資源,在IO流操作和數(shù)據(jù)庫操作中會見到
  • C:案例演示
    • finally關鍵字的特點及作用

19.10_異常(finally關鍵字的面試題)

  • A:面試題1
    • final,finally和finalize的區(qū)別
    • final可以修飾類赔蒲、方法泌神、變量
    • finally是try語句中的一個語句體,用來釋放資源舞虱,不能單獨使用
    • finalize是Object中一個方法欢际,當垃圾回收器回收類對象資源時,對象的垃圾回收器調用該方法矾兜。
  • B:面試題2
    • 如果catch里面有return語句损趋,請問finally的代碼還會執(zhí)行嗎? 如果會,請問是在return前還是return后椅寺?
    • return先執(zhí)行建立返回路徑浑槽,然后finally執(zhí)行,最后return完全返回返帕。

19.11_異常(自定義異常概述和基本使用)

  • A:為什么需要自定義異常
    • 讓用戶根據(jù)異常名稱快速定位異常
    • 舉例:人的年齡
  • B:自定義異常概述
    • 繼承自Exception
    • 繼承自RuntimeException
  • C:案例演示
    • 自定義異常的基本使用

19.12_異常(異常的注意事項及如何使用異常處理)

  • A:異常注意事項
    • a:子類【重寫】父類方法時桐玻,子類的方法必須拋出【相同的異常】或父類異常的【子類】溉旋。(父親壞了,兒子不能比父親更壞)
    • b:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
    • c:如果被重寫的方法沒有異常拋出,那么子類的方法絕對不可以拋出異常,如果子類方法內(nèi)有異常發(fā)生,那么子類只能try,不能throws
  • B:如何使用異常處理
    • 原則:如果該功能內(nèi)部可以將問題處理,用try,如果處理不了,交由調用者處理,這是用throws

    • 區(qū)別:

      • 后續(xù)程序需要繼續(xù)運行就try
      • 后續(xù)程序不需要繼續(xù)運行就throws
    • 如果JDK沒有提供對應的異常嫉髓,需要自定義異常观腊。

19.13_異常(練習)

  • 鍵盤錄入一個int類型的整數(shù),對其求二進制表現(xiàn)形式

    • 如果錄入的整數(shù)過大,給予提示,錄入的整數(shù)過大請重新錄入一個整數(shù)BigInteger
    • 如果錄入的是小數(shù),給予提示,錄入的是小數(shù),請重新錄入一個整數(shù)
    • 如果錄入的是其他字符,給予提示,錄入的是非法字符,請重新錄入一個整數(shù)
      alt + shift + z try-catch快捷鍵
      try-catch的嵌套使用

    Scanner sc = new Scanner(System.in);
    System.out.println("請輸入一個整數(shù): ");

    while(true) {
    String line = sc.nextLine();
    try {
    int num = Integer.parseInt(line);
    System.out.println(Integer.toBinaryString(num));
    break;
    }catch(Exception e) {
    try {
    new BigInteger(line);//11111122.33333
    System.out.println(錄入有誤,您錄入的是一個過大的整數(shù)!);
    }catch(Exception e2){
    try{
    new BigDecimal(line);//11a1222.333
    System.out.println("錄入錯誤算行,您錄入的是一個小數(shù)梧油,請重新輸入一個整數(shù): ");
    }catch (Exception e1) {
    System.out.println("錄入錯誤,您錄入的是非法字符州邢,請重新輸入一個整數(shù): ");
    }
    }
    }
    }儡陨;

19.14_File類(File類的概述和構造方法)

  • A:File類的概述
    • File更應該叫做一個路徑
      • 文件路徑或者文件夾路徑
      • 路徑分為絕對路徑和相對路徑
      • 絕對路徑是一個固定的路徑,從盤符開始
      • 相對路徑相對于某個位置,在eclipse下是指當前項目下,在dos下
    • 查看API指的是當前路徑
    • 文件和目錄路徑名的抽象表示形式
  • B:構造方法
    • File(String pathname):根據(jù)一個路徑得到File對象,注意分隔符F:\java
    • File(String parent, String child):根據(jù)一個目錄和一個子文件/目錄得到File對象
    • File(File parent, String child):根據(jù)一個父File對象和一個子文件/目錄得到File對象
  • C:案例演示
    • File類的構造方法

19.15_File類(File類的創(chuàng)建功能)

  • A:創(chuàng)建功能
    • public boolean createNewFile():創(chuàng)建文件 如果存在這樣的文件褪子,就不創(chuàng)建了
    • public boolean mkdir():創(chuàng)建文件夾 如果存在這樣的文件夾,就不創(chuàng)建了
    • public boolean mkdirs():創(chuàng)建多級文件夾,如果父文件夾不存在骗村,會幫你創(chuàng)建出來
  • B:案例演示
    • File類的創(chuàng)建功能

    • 注意事項:

      • 如果你創(chuàng)建文件或者文件夾忘了寫盤符路徑嫌褪,那么,默認在項目路徑下胚股。
      • 創(chuàng)建文件時可以不指定后綴笼痛,創(chuàng)建文件夾可以指定后綴

19.16_File類(File類的重命名和刪除功能)

  • A:重命名和刪除功能
    • public boolean renameTo(File dest):把文件重命名為指定的文件路徑或剪切
    • public boolean delete():刪除文件或者文件夾
  • B:重命名注意事項
    • 如果路徑名相同,就是改名琅拌。
    • 如果路徑名不同缨伊,就是改名并剪切。
  • C:刪除注意事項:
    • Java中的刪除不走回收站进宝。
    • 要刪除一個文件夾刻坊,請注意該文件夾內(nèi)不能包含文件或者文件夾

19.17_File類(File類的判斷功能)

  • A:判斷功能
    • public boolean isDirectory():判斷是否是目錄
    • public boolean isFile():判斷是否是文件
    • public boolean exists():判斷是否存在
    • public boolean canRead():判斷是否可讀,默認都是可讀党晋,setReadable無效
    • public boolean canWrite():判斷是否可寫谭胚,可以設置
    • public boolean isHidden():判斷是否隱藏,windows中先設置隱藏
  • B:案例演示
    • File類的判斷功能

19.18_File類(File類的獲取功能)

  • A:獲取功能
    • public String getAbsolutePath():獲取絕對路徑
    • public String getPath():獲取路徑隶校,構造方法中傳入的
    • public String getName():獲取名稱
    • public long length():獲取長度漏益。字節(jié)數(shù)
    • public long lastModified():獲取最后一次的修改時間,毫秒值
    • public String[] list():獲取指定目錄下的所有文件或者文件夾的名稱數(shù)組
    • public File[] listFiles():獲取指定目錄下的所有文件或者文件夾的File數(shù)組
  • B:案例演示
    • File類的獲取功能

19.19_File類(輸出指定目錄下指定后綴的文件名)

  • A:案例演示
    • 需求:判斷 E 目錄下是否有后綴名為.txt的文件深胳,如果有绰疤,就輸出該文件名稱

19.20_File類(文件名稱過濾器的概述及使用)

  • A:文件名稱過濾器的概述

    • public String[] list(FilenameFilter filter)
    • public File[] listFiles(FileFilter filter)
  • B:文件名稱過濾器的使用

    • 需求:判斷E盤目錄下是否有后綴名為.jpg的文件,如果有舞终,就輸出該文件名稱
  • C:源碼分析

    • 帶文件名稱過濾器的list()方法的源碼

    file.list(new FilenameFilter() {
    @Override
    public boolean accept(File dir,String name) {
    File f = new File(dir,name);
    return f.isFile() && f.getName().endsWith(".jpg");
    }
    });

19.22_day19總結

把今天的知識點總結一遍轻庆。

20.01_IO流(IO流概述及其分類)

  • 1.概念
    • IO流用來處理設備之間的數(shù)據(jù)傳輸
    • Java對數(shù)據(jù)的操作是通過流的方式
    • Java用于操作流的類都在IO包中
    • 流按流向分為兩種:輸入流,輸出流敛劝。
    • 流按操作類型【單位】分為兩種:
      • 字節(jié)流 : 字節(jié)流可以操作任何數(shù)據(jù),因為在計算機中任何數(shù)據(jù)都是以字節(jié)的形式存儲的
      • 字符流 : 字符流只能操作純字符數(shù)據(jù)余爆,比較方便。
  • 2.IO流常用父類
    • 字節(jié)流的抽象父類:
      • InputStream
      • OutputStream
    • 字符流的抽象父類:
      • Reader
      • Writer
  • 3.IO程序書寫
    • 使用前夸盟,導入IO包中的類
    • 使用時蛾方,進行IO異常處理
    • 使用后,釋放資源

20.02_IO流(FileInputStream)

  • read()一次讀取一個字節(jié)
  •   FileInputStream fis = new FileInputStream("aaa.txt");   //創(chuàng)建一個文件輸入流對象,并關聯(lián)aaa.txt
      int b;                                                  //定義變量,記錄每次讀到的字節(jié)
      while((b = fis.read()) != -1) {                         //將每次讀到的字節(jié)賦值給b并判斷是否是-1
          System.out.println(b);                              //打印每一個字節(jié)
      }
      
      fis.close();                                            //關閉流釋放資源
    

20.03_IO流(read()方法返回值為什么是int)

  • read()方法讀取的是一個字節(jié),為什么返回是int,而不是byte
  •   因為字節(jié)輸入流可以操作任意類型的文件,比如圖片音頻等,這些文件底層都是以二進制形式的存儲的,如果每次讀取都返回byte,有可能在讀到中間的時候遇到11111111
      那么這11111111是byte類型的-1,我們的程序是遇到-1就會停止不讀了,后面的數(shù)據(jù)就讀不到了,所以在讀取的時候用int類型接收,如果11111111會在其前面補上
      24個0湊足4個字節(jié),那么byte類型的-1就變成int類型的255了這樣可以保證整個數(shù)據(jù)讀完,而結束標記的-1就是int類型
    

20.04_IO流(FileOutputStream)

  • write()一次寫出一個字節(jié)
  •   FileOutputStream fos = new FileOutputStream("bbb.txt"); //如果沒有bbb.txt,會創(chuàng)建出一個
      //fos.write(97);                        //雖然寫出的是一個int數(shù),但是在寫出的時候會將前面的24個0去掉,所以寫出的一個byte
      fos.write(98);
      fos.write(99);
      fos.close();
    

20.05_IO流(FileOutputStream追加)

  • A:案例演示
    • FileOutputStream的構造方法寫出數(shù)據(jù)如何實現(xiàn)數(shù)據(jù)的追加寫入
  •   FileOutputStream fos = new FileOutputStream("bbb.txt",true);    //如果沒有bbb.txt,會創(chuàng)建出一個
      //fos.write(97);                        //雖然寫出的是一個int數(shù),但是在寫出的時候會將前面的24個0去掉,所以寫出的一個byte
      fos.write(98);
      fos.write(99);
      fos.close();
    

20.06_IO流(拷貝圖片)

  • FileInputStream讀取
  • FileOutputStream寫出

20.07_IO流(拷貝音頻文件畫原理圖)

  • A:案例演示

    • 字節(jié)流一次讀寫一個字節(jié)復制音頻mp3文件
  • 弊端:效率太低

      FileInputStream fis = new FileInputStream("致青春.mp3");   //創(chuàng)建輸入流對象,關聯(lián)致青春.mp3
      FileOutputStream fos = new FileOutputStream("copy.mp3");//創(chuàng)建輸出流對象,關聯(lián)copy.mp3
      
      int b;
      while((b = fis.read()) != -1) {
          fos.write(b);
      }
      
      fos.close();
      fis.close();
    

20.08_IO流(字節(jié)數(shù)組拷貝之a(chǎn)vailable()方法)

  • A:案例演示

    • int read(byte[] b):一次讀取一個字節(jié)數(shù)組
    • write(byte[] b):一次寫出一個字節(jié)數(shù)組
    • available()獲取讀的文件所有的字節(jié)個數(shù)
  • 弊端:有可能會內(nèi)存溢出

      FileInputStream fis = new FileInputStream("致青春.mp3");
      FileOutputStream fos = new FileOutputStream("copy.mp3");
      byte[] arr = new byte[fis.available()];                 //根據(jù)文件大小做一個字節(jié)數(shù)組
      fis.read(arr);                                          //將文件上的所有字節(jié)讀取到數(shù)組中
      fos.write(arr);                                         //將數(shù)組中的所有字節(jié)一次寫到了文件上
      fis.close();
      fos.close();
    

20.09_IO流(定義小數(shù)組)

  • write(byte[] b)
  • write(byte[] b, int off, int len)寫出有效的字節(jié)個數(shù)

20.10_IO流(定義小數(shù)組的標準格式)

  • A:案例演示
    • 字節(jié)流一次讀寫一個字節(jié)數(shù)組復制圖片和視頻
      FileInputStream fis = new FileInputStream("致青春.mp3");
      FileOutputStream fos = new FileOutputStream("copy.mp3");
      int len;
      byte[] arr = new byte[1024 * 8]; //自定義字節(jié)數(shù)組

      while((len = fis.read(arr)) != -1) {
      //fos.write(arr);
      fos.write(arr, 0, len); //寫出字節(jié)數(shù)組寫出有效個字節(jié)個數(shù)
      }

      fis.close();
      fos.close();

20.11_IO流(BufferedInputStream和BufferOutputStream拷貝)

  • A:緩沖思想

    • 字節(jié)流一次讀寫一個數(shù)組的速度明顯比一次讀寫一個字節(jié)的速度快很多上陕,
    • 這是加入了數(shù)組這樣的緩沖區(qū)效果桩砰,java本身在設計的時候,
    • 也考慮到了這樣的設計思想(裝飾設計模式后面講解)释簿,所以提供了字節(jié)緩沖區(qū)流
  • B.BufferedInputStream

    • BufferedInputStream內(nèi)置了一個緩沖區(qū)(數(shù)組)
    • 從BufferedInputStream中讀取一個字節(jié)時
    • BufferedInputStream會一次性從文件中讀取8192個, 存在緩沖區(qū)中, 返回給程序一個
    • 程序再次讀取時, 就不用找文件了, 直接從緩沖區(qū)中獲取
    • 直到緩沖區(qū)中所有的都被使用過, 才重新從文件中讀取8192個
  • C.BufferedOutputStream

    • BufferedOutputStream也內(nèi)置了一個緩沖區(qū)(數(shù)組)
    • 程序向流中寫出字節(jié)時, 不會直接寫到文件, 先寫到緩沖區(qū)中
    • 直到緩沖區(qū)寫滿, BufferedOutputStream才會把緩沖區(qū)中的數(shù)據(jù)一次性寫到文件里
  • D.拷貝的代碼

      FileInputStream fis = new FileInputStream("致青春.mp3");           //創(chuàng)建文件輸入流對象,關聯(lián)致青春.mp3
      BufferedInputStream bis = new BufferedInputStream(fis);         //創(chuàng)建緩沖區(qū)對fis裝飾
      FileOutputStream fos = new FileOutputStream("copy.mp3");        //創(chuàng)建輸出流對象,關聯(lián)copy.mp3
      BufferedOutputStr·eam bos = new BufferedOutputStream(fos);      //創(chuàng)建緩沖區(qū)對fos裝飾
      
      int b;
      while((b = bis.read()) != -1) {     
          bos.write(b);
      }
      
      bis.close();                        //只關裝飾后的對象即可
      bos.close();
    
  • E.小數(shù)組的讀寫和帶Buffered的讀取哪個更快?

    • 定義小數(shù)組如果是8192個字節(jié)大小和Buffered比較的話
    • 定義小數(shù)組會略勝一籌,因為讀和寫操作的是同一個數(shù)組
    • 而Buffered操作的是兩個數(shù)組

20.12_IO流(flush和close方法的區(qū)別)

  • flush()方法
    • 用來刷新緩沖區(qū)的,刷新后可以再次寫出
  • close()方法
    • 用來關閉流釋放資源的的,如果是帶緩沖區(qū)的流對象的close()方法,不但會關閉流,還會再關閉流之前刷新緩沖區(qū),關閉后不能再寫出

20.13_IO流(字節(jié)流讀寫中文)

  • 字節(jié)流讀取中文的問題
    • 字節(jié)流在讀中文的時候有可能會讀到半個中文,造成亂碼
  • 字節(jié)流寫出中文的問題
    • 字節(jié)流直接操作的字節(jié),所以寫出中文必須將字符串轉換成字節(jié)數(shù)組
    • 寫出回車換行 write("\r\n".getBytes());

20.14_IO流(流的標準處理異常代碼1.6版本及其以前)

  • try finally嵌套

      FileInputStream fis = null;
      FileOutputStream fos = null;
      try {
          fis = new FileInputStream("aaa.txt");
          fos = new FileOutputStream("bbb.txt");
          int b;
          while((b = fis.read()) != -1) {
              fos.write(b);
          }
      }catch (Exception e) {
          e.print...();
      }finally {
          try {
              if(fis != null)
                  fis.close();
          }finally {
              if(fos != null)
                  fos.close();
          }
      }
    

20.15_IO流(流的標準處理異常代碼1.7版本)

  • try close 自動回收資源

      try(
          FileInputStream fis = new FileInputStream("aaa.txt");
          FileOutputStream fos = new FileOutputStream("bbb.txt");
          //MyClose mc = new MyClose();
      ){
          int b;
          while((b = fis.read()) != -1) {
              fos.write(b);
          }
      }catch(Exception e) {
          ...
      }
    
  • 原理

    • 在try()中創(chuàng)建的流對象必須實現(xiàn)了AutoCloseable這個接口,如果實現(xiàn)了,在try后面的{}(讀寫代碼)執(zhí)行后就會自動調用,流對象的close方法將流關掉

20.16_IO流(圖片加密)

  • 給圖片加密

      BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg"));
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg"));
      
      int b;
      while((b = bis.read()) != -1) {
          bos.write(b ^ 123);
      }
      
      bis.close();
      bos.close();
    

20.17_IO流(拷貝文件) E://dir//a.txt

  • 在控制臺錄入文件的路徑,將文件拷貝到當前項目下

      Scanner sc = new Scanner(System.in);
      System.out.println("請輸入一個文件路徑");
      String line = sc.nextLine();                //將鍵盤錄入的文件路徑存儲在line中
      File file = new File(line);                 //封裝成File對象
      FileInputStream fis = new FileInputStream(file);
      FileOutputStream fos = new FileOutputStream(file.getName());
      
      int len;
      byte[] arr = new byte[8192];                //定義緩沖區(qū)
      while((len = fis.read(arr)) != -1) {
          fos.write(arr,0,len);
      }
      
      fis.close();
      fos.close();
    

20.18_IO流(錄入數(shù)據(jù)拷貝到文件)

  • 將鍵盤錄入的數(shù)據(jù)拷貝到當前項目下的text.txt文件中,鍵盤錄入數(shù)據(jù)當遇到quit時就退出

      Scanner sc = new Scanner(System.in);
      FileOutputStream fos = new FileOutputStream("text.txt");
      System.out.println("請輸入:");
    
      while(true) {
          String line = sc.nextLine();
          if("quit".equals(line))
              break;
          fos.write(line.getBytes());
          fos.write("\r\n".getBytes());
      }
      
      fos.close();
    

21.01_IO流(字符流FileReader)

  • 1.字符流是什么
    • 字符流是可以直接讀寫字符的IO流
    • 字符流讀取字符, 就要先讀取到字節(jié)數(shù)據(jù), 然后轉為字符. 如果要寫出字符, 需要把字符轉為字節(jié)再寫出.
    • 只有純文本文件亚隅,我們才選擇 字符流進行操作啄育,提高我們效率旺聚,簡化操作
  • 2.FileReader
    • FileReader類的read()方法可以按照字符大小讀取
  •   FileReader fr = new FileReader("aaa.txt");              //創(chuàng)建輸入流對象,關聯(lián)aaa.txt
      int ch;
      while((ch = fr.read()) != -1) {                         //將讀到的字符賦值給ch
          System.out.println((char)ch);                       //將讀到的字符強轉后打印
      }
      
      fr.close();                                             //關流 
    

21.02_IO流(字符流FileWriter)

  • FileWriter類的write()方法可以自動把字符轉為字節(jié)寫出

  • 注意: Writer中自帶緩沖區(qū),注意刷新或關閉流。

      FileWriter fw = new FileWriter("aaa.txt");
      fw.write("aaa");
      fw.close();
    

21.03_IO流(字符流的拷貝)

FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");

int ch;
while((ch = fr.read()) != -1) {
    fw.write(ch);
}

fr.close();
fw.close();

21.04_IO流(什么情況下使用字符流)

  • 字符流也可以拷貝文本文件, 但不推薦使用. 因為讀取時會把字節(jié)轉為字符, 寫出時還要把字符轉回字節(jié).
  • 程序需要讀取一段文本, 或者需要寫出一段文本的時候可以使用字符流址貌。
  • 讀取的時候是按照字符的大小讀取的,不會出現(xiàn)半個中文
  • 寫出的時候可以直接將字符串寫出,不用轉換為字節(jié)數(shù)組

21.05_IO流(字符流是否可以拷貝非純文本的文件)

  • 不可以拷貝非純文本的文件
  • 因為在讀的時候會將字節(jié)轉換為字符,在轉換過程中,可能找不到對應的字符,就會用?代替,寫出的時候會將字符轉換成字節(jié)寫出去
  • 如果是?,直接寫出,這樣寫出之后的文件就亂了,看不了了

21.06_IO流(自定義字符數(shù)組的拷貝)

  •   FileReader fr = new FileReader("aaa.txt");          //創(chuàng)建字符輸入流,關聯(lián)aaa.txt
      FileWriter fw = new FileWriter("bbb.txt");          //創(chuàng)建字符輸出流,關聯(lián)bbb.txt
      
      int len;
      char[] arr = new char[1024*8];                      //創(chuàng)建字符數(shù)組
      while((len = fr.read(arr)) != -1) {                 //將數(shù)據(jù)讀到字符數(shù)組中
          fw.write(arr, 0, len);                          //從字符數(shù)組將數(shù)據(jù)寫到文件上
      }
      
      fr.close();                                         //關流釋放資源
      fw.close(); 
    

21.07_IO流(帶緩沖的字符流)

  • BufferedReader的read()方法讀取字符時會一次讀取若干字符到緩沖區(qū), 然后逐個返回給程序, 降低讀取文件的次數(shù), 提高效率
  • BufferedWriter的write()方法寫出字符時會先寫到緩沖區(qū), 緩沖區(qū)寫滿時才會寫到文件, 降低寫文件的次數(shù), 提高效率
  •   BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));  //創(chuàng)建字符輸入流對象,關聯(lián)aaa.txt
      BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));  //創(chuàng)建字符輸出流對象,關聯(lián)bbb.txt
      
      int ch;             
      while((ch = br.read()) != -1) {     //read一次,會先將緩沖區(qū)讀滿,從緩沖去中一個一個的返給臨時變量ch
          bw.write(ch);                   //write一次,是將數(shù)據(jù)裝到字符數(shù)組,裝滿后再一起寫出去
      }
      
      br.close();                         //關流
      bw.close();  
    

21.08_IO流(readLine()和newLine()方法)

  • BufferedReader的readLine()方法可以讀取一行字符(不包含換行符號)
  • BufferedWriter的newLine()可以輸出一個跨平臺的換行符號"\r\n"
  •   BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));
      BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));
      String line;
      while((line = br.readLine()) != null) {
          bw.write(line);
          //bw.write("\r\n");                 //只支持windows系統(tǒng)
          bw.newLine();                       //跨平臺的
      }
      
      br.close();
      bw.close(); 
    

21.09_IO流(將文本反轉)

  • 將一個文本文檔上的文本反轉,第一行和倒數(shù)第一行交換,第二行和倒數(shù)第二行交換

21.10_IO流(LineNumberReader) 了解

  • LineNumberReader是BufferedReader的子類, 具有相同的功能, 并且可以統(tǒng)計行號
    • 調用getLineNumber()方法可以獲取當前行號
    • 調用setLineNumber()方法可以設置當前行號
  •   LineNumberReader lnr = new LineNumberReader(new FileReader("aaa.txt"));
      String line;
      lnr.setLineNumber(100);                                 //設置行號
      while((line = lnr.readLine()) != null) {
          System.out.println(lnr.getLineNumber() + ":" + line);//獲取行號
      }
      
      lnr.close(); 
    

21.11_IO流(裝飾設計模式)

  • 設計模式: 前人總結的乡摹,為了解決特定場景問題所提出的解決方案弱匪,常用的有23種畔裕,很巧妙,提高程序員工作效率【遇到類似問題隘擎,直接套用對應的設計模式即可】殴穴。
  • 可以對類功能進行增強,同時保證低耦合
  • IO流中類 就是裝飾模式的具體應用货葬。
  •   //公共接口
      interface Coder {
          public void code();
      }
      
      //具體類
      class Student implements Coder {
      
          @Override
          public void code() {
              System.out.println("javase");
              System.out.println("javaweb");
          }
          
      }
      
      //裝飾器類
      class BriupStudent implements Coder {
          private Student s;                      //獲取到被包裝的類的引用
          public BriupStudent(Student s) {        //通過構造函數(shù)創(chuàng)建對象的時候,傳入被包裝的對象
              this.s = s;
          }
    
          @Override
          public void code() {                    //對其原有功能進行升級
              s.code();
              System.out.println("唱歌");
              System.out.println("跳舞");
              System.out.println("做飯");
              System.out.println("洗衣服");
          }
          
      } 
      
      //編碼: 開閉原則【對修改關閉采幌,對擴展開放】
      main() {
          //Coder stu = new Student();
          //stu.code();
    
          Coder stu = new BriupStudent(new Student());
          stu.code();
      }
    

21.12_IO流(使用指定的碼表讀寫字符)

  • FileReader是使用默認碼表讀取文件, 如果需要使用指定碼表讀取, 那么可以使用InputStreamReader(字節(jié)流,編碼表)
  • FileWriter是使用默認碼表寫出文件, 如果需要使用指定碼表寫出, 那么可以使用OutputStreamWriter(字節(jié)流,編碼表)
  •   BufferedReader br =                                     //高效的用指定的編碼表讀
              new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));
      BufferedWriter bw =                                     //高效的用指定的編碼表寫
              new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));
      int ch;
      while((ch = br.read()) != -1) {
          bw.write(ch);
      }
      
      br.close();
      bw.close();
    

21.13_IO流(轉換流圖解)

  • 畫圖分析轉換流

21.14_IO流(獲取文本上字符出現(xiàn)的次數(shù))

  • 獲取一個文本上每個字符出現(xiàn)的次數(shù),將結果寫在times.txt上
  • TreeMap 字符 次數(shù) Test7Count.java
  • a: 10 緩沖流
  • b: 13
  • 中: 16

21.15_IO流(試用版軟件)

  • 當我們下載一個試用版軟件,沒有購買正版的時候,每執(zhí)行一次就會提醒我們還有多少次使用機會用學過的IO流知識,模擬試用版軟件,試用10次機會,執(zhí)行一次就提示一次您還有幾次機會,如果次數(shù)到了提示請購買正版
  • 配置信息 軟件安裝的時間 配置文件config.txt
  • 一個月以內(nèi)可以正常使用,一個月以后就無法使用震桶,提示你購買正版.

21.16_File類(遞歸)

  • 函數(shù)自己調用自己休傍,就是遞歸
  • 注意: 書寫遞歸函數(shù),一定要設置結束條件蹲姐,不能讓程序一直遞歸下去磨取。
  • 遞歸的好處,在特定場景中很容易幫助理解柴墩;弊端是效率低忙厌,還可能造成棧內(nèi)存溢出
  • 5的階乘
  • 波非那切數(shù) 1 1 2 3 5 8 13 21 34 55
  • f(n){//5
  • if(n == 1 || n == 2)
  •   return 1; 
    
  • return f(n-1) + f(n-2);
  • }

21.17_File類(練習)

  • 需求:從鍵盤輸入接收一個文件夾路徑,打印出該文件夾下所有的.java文件名

21.18_File類遞歸練習(統(tǒng)計該文件夾大小)

  • 需求:1,從鍵盤接收一個文件夾路徑,統(tǒng)計該文件夾大小
  • 求一個目錄的長度: 求出來所有子文件 的長度和
  • E:\a的大小: test.java + dir1大小 + dir2大小
  • E:\a\test.java
  • E:\a\dir1\a.txt
  • E:\a\dir2\b.txt c.txt

21.19_IO流(總結)

  • 1.會用BufferedReader讀取GBK碼表和UTF-8碼表的字符
  • 2.會用BufferedWriter寫出字符到GBK碼表和UTF-8碼表的文件中
  • 3.會使用BufferedReader從鍵盤讀取一行

22.01_IO流(序列流)(了解)

  • 1.什么是序列流
    • 序列流可以把多個字節(jié)輸入流整合成一個, 從序列流中讀取數(shù)據(jù)時, 將從被整合的第一個流開始讀, 讀完一個之后繼續(xù)讀第二個, 以此類推.
  • 2.使用方式
    • 整合兩個: SequenceInputStream(InputStream, InputStream)
    •   FileInputStream fis1 = new FileInputStream("a.txt");            //創(chuàng)建輸入流對象,關聯(lián)a.txt
        FileInputStream fis2 = new FileInputStream("b.txt");            //創(chuàng)建輸入流對象,關聯(lián)b.txt
        SequenceInputStream sis = new SequenceInputStream(fis1, fis2);  //將兩個流整合成一個流
        FileOutputStream fos = new FileOutputStream("c.txt");           //創(chuàng)建輸出流對象,關聯(lián)c.txt
        
        int b;
        while((b = sis.read()) != -1) {                                 //用整合后的讀
            fos.write(b);                                               //寫到指定文件上
        }
        
        sis.close();
        fos.close(); 
      

22.02_IO流(序列流整合多個)(了解)

  • 整合多個: SequenceInputStream(Enumeration)
  •   FileInputStream fis1 = new FileInputStream("a.txt");    //創(chuàng)建輸入流對象,關聯(lián)a.txt
      FileInputStream fis2 = new FileInputStream("b.txt");    //創(chuàng)建輸入流對象,關聯(lián)b.txt
      FileInputStream fis3 = new FileInputStream("c.txt");    //創(chuàng)建輸入流對象,關聯(lián)c.txt
      Vector<InputStream> v = new Vector<>();                 //創(chuàng)建vector集合對象
      v.add(fis1);                                            //將流對象添加
      v.add(fis2);
      v.add(fis3);
      Enumeration<InputStream> en = v.elements();             //獲取枚舉引用
      SequenceInputStream sis = new SequenceInputStream(en);  //傳遞給SequenceInputStream構造
      FileOutputStream fos = new FileOutputStream("d.txt");
      int b;
      while((b = sis.read()) != -1) {
          fos.write(b);
      }
    
      sis.close();
      fos.close();
    

22.03_IO流(內(nèi)存輸出流*****)(掌握)

  • 1.什么是內(nèi)存輸出流
    • 該輸出流可以向內(nèi)存中寫數(shù)據(jù), 把內(nèi)存當作一個緩沖區(qū), 寫出之后可以一次性獲取出所有數(shù)據(jù)
  • 2.使用方式
    • 創(chuàng)建對象: new ByteArrayOutputStream()
    • 寫出數(shù)據(jù): write(int), write(byte[])
    • 獲取數(shù)據(jù): toByteArray() toString()
    •   FileInputStream fis = new FileInputStream("a.txt");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int b;
        while((b = fis.read()) != -1) {
            baos.write(b);
        }
        
        //byte[] newArr = baos.toByteArray();               //將內(nèi)存緩沖區(qū)中所有的字節(jié)存儲在newArr中
        //System.out.println(new String(newArr));
        System.out.println(baos);
        fis.close();
      

22.04_IO流(內(nèi)存輸出流之面試題)(掌握)

  • 定義一個文件輸入流,調用read(byte[] b)方法,將a.txt文件中的內(nèi)容打印出來(byte數(shù)組大小限制為5)
  •       FileInputStream fis = new FileInputStream("a.txt");             //創(chuàng)建字節(jié)輸入流,關聯(lián)a.txt
          ByteArrayOutputStream baos = new ByteArrayOutputStream();       //創(chuàng)建內(nèi)存輸出流
          byte[] arr = new byte[5];                                       //創(chuàng)建字節(jié)數(shù)組,大小為5
          int len;
          while((len = fis.read(arr)) != -1) {                            //將文件上的數(shù)據(jù)讀到字節(jié)數(shù)組中
              baos.write(arr, 0, len);                                    //將字節(jié)數(shù)組的數(shù)據(jù)寫到內(nèi)存緩沖區(qū)中
          }
          System.out.println(baos);                                       //將內(nèi)存緩沖區(qū)的內(nèi)容轉換為字符串打印
          fis.close();
    

22.05_IO流(對象操作流ObjectOutputStream)(重點掌握)

  • 1.什么是對象操作流
    • 該流可以將一個對象寫出, 或者讀取一個對象到程序中. 也就是執(zhí)行了序列化和反序列化的操作.
  • 2.使用方式
    • 寫出: new ObjectOutputStream(OutputStream), writeObject()

        public class Demo3_ObjectOutputStream {
      
            /**
             * @param args
             * @throws IOException 
             * 將對象寫出,序列化
             */
            public static void main(String[] args) throws IOException {
                Person p1 = new Person("張三", 23);
                Person p2 = new Person("李四", 24);
        //      FileOutputStream fos = new FileOutputStream("e.txt");
        //      fos.write(p1);
        //      FileWriter fw = new FileWriter("e.txt");
        //      fw.write(p1);
                //無論是字節(jié)輸出流,還是字符輸出流都不能直接寫出對象
                ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e.txt"));//創(chuàng)建對象輸出流
                oos.writeObject(p1);
                oos.writeObject(p2);
                oos.close();
            }
        
        }
      

22.06_IO流(對象操作流ObjectInputStream)(了解)

  • 讀取: new ObjectInputStream(InputStream), readObject()
    •   public class Demo3_ObjectInputStream {
      
            /**
             * @param args
             * @throws IOException 
             * @throws ClassNotFoundException 
             * @throws FileNotFoundException 
             * 讀取對象,反序列化
             */
            public static void main(String[] args) throws IOException, ClassNotFoundException {
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e.txt"));
                Person p1 = (Person) ois.readObject();
                Person p2 = (Person) ois.readObject();
                System.out.println(p1);
                System.out.println(p2);
                ois.close();
            }
        
        }
      

22.07_IO流(對象操作流優(yōu)化)(了解)

* 將對象存儲在集合中寫出

Person p1 = new Person("張三", 23);
Person p2 = new Person("李四", 24);
Person p3 = new Person("馬哥", 18);
Person p4 = new Person("輝哥", 20);

ArrayList<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f.txt"));
oos.writeObject(list);                                  //寫出集合對象

oos.close();
  • 讀取到的是一個集合對象

      ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f.txt"));
          ArrayList<Person> list = (ArrayList<Person>)ois.readObject();   //泛型在運行期會被擦除,索引運行期相當于沒有泛型
                                                                          //想去掉黃色可以加注解                    @SuppressWarnings("unchecked")
          for (Person person : list) {
              System.out.println(person);
          }
      
      ois.close();
    

22.08_IO流(加上id號)(了解)

  • 注意
    • 要寫出的對象必須實現(xiàn)Serializable接口才能被序列化
    • 不用必須加id號

22.09_IO流(打印流的概述和特點)(掌握)

  • 1.什么是打印流
    • 該流可以很方便的將對象的toString()結果輸出, 并且自動加上換行, 而且可以使用【自動刷出】的模式

    • System.out就是一個PrintStream, 其默認向控制臺輸出信息

        PrintStream ps = System.out;
        ps.println(97);                 //其實底層用的是Integer.toString(x),將x轉換為數(shù)字字符串打印
        ps.println("xxx");
        ps.println(new Person("張三", 23));
        Person p = null;
        ps.println(p);                  //如果是null,就返回null,如果不是null,就調用對象的toString()
      
  • 2.使用方式
    • 打印: print(), println()

    • 自動刷出: PrintWriter(OutputStream out, boolean autoFlush, String encoding) 江咳,只針對println方法逢净,沒什么大用處。

    • 打印流只操作【數(shù)據(jù)目的】

        PrintWriter pw = new PrintWriter(new FileOutputStream("g.txt"), true);
        pw.write(97);
        pw.print("大家好");
        pw.println("你好");               //自動刷出,只針對的是println方法
        pw.close();
      

22.10_IO流(標準輸入輸出流概述和輸出語句)

  • 1.什么是標準輸入輸出流(掌握)
    • System.in是InputStream, 標準輸入流, 默認可以從鍵盤輸入讀取字節(jié)數(shù)據(jù)
    • System.out是PrintStream, 標準輸出流, 默認可以向Console中輸出字符和字節(jié)數(shù)據(jù)
  • 2.修改標準輸入輸出流(了解)
    • 修改輸入流: System.setIn(InputStream)
    • 修改輸出流: System.setOut(PrintStream)
    •   System.setIn(new FileInputStream("a.txt"));             //修改標準輸入流
        System.setOut(new PrintStream("b.txt"));                //修改標準輸出流
        
        InputStream in = System.in;                             //獲取標準輸入流
        PrintStream ps = System.out;                            //獲取標準輸出流
        int b;
        while((b = in.read()) != -1) {                          //從a.txt上讀取數(shù)據(jù)
            ps.write(b);                                        //將數(shù)據(jù)寫到b.txt上
        }
        
        in.close();
        ps.close();
      

22.11_IO流(修改標準輸入輸出流拷貝圖片)(了解)

    System.setIn(new FileInputStream("IO圖片.png"));      //改變標準輸入流
    System.setOut(new PrintStream("copy.png"));         //改變標準輸出流
    
    InputStream is = System.in;                         //獲取標準輸入流
    PrintStream ps = System.out;                        //獲取標準輸出流
    
    int len;
    byte[] arr = new byte[1024 * 8];
    
    while((len = is.read(arr)) != -1) {
        ps.write(arr, 0, len);
    }
    
    is.close();
    ps.close();

22.11_IO流(兩種方式實現(xiàn)鍵盤錄入)(了解)

  • A:BufferedReader的readLine方法
    • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  • B:Scanner方式

22.12_IO流(隨機訪問流概述和讀寫數(shù)據(jù))(了解)

  • A:隨機訪問流概述

    • RandomAccessFile概述
    • RandomAccessFile類不屬于流歼指,是Object類的子類爹土。但它融合了InputStream和OutputStream的功能。
    • 支持對隨機訪問文件的讀取和寫入踩身。
  • B:read(),write(),seek()

    • seek從0開始

22.13_IO流(數(shù)據(jù)輸入輸出流)(了解)

  • 1.什么是數(shù)據(jù)輸入輸出流
    • DataInputStream, DataOutputStream可以按照基本數(shù)據(jù)類型大小讀寫數(shù)據(jù)
    • 例如按Long大小寫出一個數(shù)字, 寫出時該數(shù)據(jù)占8字節(jié). 讀取的時候也可以按照Long類型讀取, 一次讀取8個字節(jié).
  • 2.使用方式
    • DataOutputStream(OutputStream), writeInt(), writeLong()

        DataOutputStream dos = new DataOutputStream(new FileOutputStream("b.txt"));
        dos.writeInt(997);
        dos.writeInt(998);
        dos.writeInt(999);
        
        dos.close();
      
    • DataInputStream(InputStream), readInt(), readLong()

        DataInputStream dis = new DataInputStream(new FileInputStream("b.txt"));
        int x = dis.readInt();
        int y = dis.readInt();
        int z = dis.readInt();
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
        dis.close();
      

22.14_IO流(Properties的概述和作為Map集合的使用)(掌握)

  • A:Properties的概述
    • Properties 類表示了一個持久的屬性集胀茵。
    • Properties 可保存在流中或從流中加載。
    • 屬性列表中每個鍵及其對應值都是一個字符串挟阻。
  • B:案例演示
    • Properties作為Map集合的使用

22.15_IO流(Properties的特殊功能使用)(掌握)

  • A:Properties的特殊功能
    • public Object setProperty(String key,String value)
    • public String getProperty(String key)
    • public Set<String> stringPropertyNames()
  • B:案例演示
    • Properties的特殊功能

22.16_IO流(Properties的load()和store()功能)(了解)

  • A:Properties的load()和store()功能
  • B:案例演示
    • Properties的load()和store(OutputStream out,String comments)功能琼娘;
    • String comments是對列表參數(shù)的描述,null與非null值都可以附鸽。

24.01_多線程(多線程的引入)(了解)

  • 1.什么是線程
    • 線程是程序執(zhí)行的一條路徑, 一個進程中可以包含多條線程
    • QQ聊天 進程 你在給同學發(fā)信息的同時脱拼,能否接收其他同學的消息?提高效率
    • 進程拒炎,是一個應用程序的執(zhí)行流程挪拟,進程是資源分配的最小單位
    • 多線程并發(fā)執(zhí)行可以提高程序的效率, 可以同時完成多項工作
  • 2.多線程的應用場景
    • 紅蜘蛛同時共享屏幕給多個電腦
    • 迅雷開啟多條線程一起下載
    • QQ同時和多個人一起視頻
    • 服務器同時處理多個客戶端請求

24.02_多線程(多線程并行和并發(fā)的區(qū)別)(了解)

  • 并行就是兩個任務同時運行挨务,就是甲任務進行的同時击你,乙任務也在進行玉组。(需要多核CPU)
  • 并發(fā)是指兩個任務都請求運行,而處理器只能按受一個任務丁侄,就把這兩個任務安排輪流進行惯雳,由于時間間隔較短,使人感覺兩個任務都在運行鸿摇。
  • 比如我跟兩個網(wǎng)友聊天石景,左手操作一個電腦跟甲聊,同時右手用另一臺電腦跟乙聊天拙吉,這就叫并行潮孽。
  • 如果用一臺電腦我先給甲發(fā)個消息,然后立刻再給乙發(fā)消息筷黔,然后再跟甲聊往史,再跟乙聊。這就叫并發(fā)佛舱。

24.03_多線程(Java程序運行原理和JVM的啟動是多線程的嗎)(了解)

  • A:Java程序運行原理

    • Java命令會啟動java虛擬機椎例,啟動JVM,等于啟動了一個應用程序请祖,也就是啟動了一個進程订歪。該進程會自動啟動一個 “主線程” ,然后主線程去調用某個類的 main 方法肆捕。
  • B:JVM的啟動是多線程的嗎

    • JVM啟動至少啟動了垃圾回收線程和主線程刷晋,所以是多線程的。

24.04_多線程(多線程程序實現(xiàn)的方式1)(掌握)

  • 1.繼承Thread
    • 定義類繼承Thread
    • 重寫run方法
    • 把新線程要做的事寫在run方法中
    • 創(chuàng)建線程對象
    • 開啟新線程, 內(nèi)部會自動執(zhí)行run方法
    •   public class Demo2_Thread {
      
            /**
             * @param args
             */
            public static void main(String[] args) {
                MyThread mt = new MyThread();                           //4,創(chuàng)建自定義類的對象
                mt.start();                                             //5,開啟線程
                
                for(int i = 0; i < 3000; i++) {
                    System.out.println("bb");
                }
            }
        
        }
        class MyThread extends Thread {                                 //1,定義類繼承Thread
            public void run() {                                         //2,重寫run方法
                for(int i = 0; i < 3000; i++) {                         //3,將要執(zhí)行的代碼,寫在run方法中
                    System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
                }
            }
        }
      

24.05_多線程(多線程程序實現(xiàn)的方式2)(掌握)

  • 2.實現(xiàn)Runnable
    • 定義類實現(xiàn)Runnable接口

    • 實現(xiàn)run方法

    • 把新線程要做的事寫在run方法中

    • 創(chuàng)建自定義的Runnable的子類對象

    • 創(chuàng)建Thread對象, 傳入Runnable

    • 調用start()開啟新線程, 內(nèi)部會自動調用Runnable的run()方法

        public class Demo3_Runnable {
            /**
             * @param args
             */
            public static void main(String[] args) {
                MyRunnable mr = new MyRunnable();                       //4,創(chuàng)建自定義類對象
                //Runnable target = new MyRunnable();
                Thread t = new Thread(mr);                              //5,將其當作參數(shù)傳遞給Thread的構造函數(shù)
                t.start();                                              //6,開啟線程
                
                for(int i = 0; i < 3000; i++) {
                    System.out.println("bb");
                }
            }
        }
        
        class MyRunnable implements Runnable {                          //1,自定義類實現(xiàn)Runnable接口
            @Override
            public void run() {                                         //2,重寫run方法
                for(int i = 0; i < 3000; i++) {                         //3,將要執(zhí)行的代碼,寫在run方法中
                    System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
                }
            }
            
        }
      

24.06_多線程(實現(xiàn)Runnable的原理)(了解)

  • 查看源碼
    • 1,看Thread類的構造函數(shù),傳遞了Runnable接口的引用
    • 2,通過init()方法找到傳遞的target給成員變量的target賦值
    • 3,查看run方法,發(fā)現(xiàn)run方法中有判斷,如果target不為null就會調用Runnable接口子類對象的run方法

24.07_多線程(兩種方式的區(qū)別)(掌握)

  • 查看源碼的區(qū)別:

    • a.繼承Thread: 由于子類重寫了Thread類的run(), 當調用start()時, 直接找子類的run()方法
    • b.實現(xiàn)Runnable: 構造函數(shù)中傳入了Runnable的引用, 成員變量記住了它, start()調用run()方法時內(nèi)部判斷成員變量Runnable的引用是否為空, 不為空編譯時看的是Runnable的run(),運行時執(zhí)行的是子類的run()方法
    • 好處是:可以直接使用Thread類中的方法,代碼簡單繼承Thread
    • 弊端是:如果已經(jīng)有了父類,就不能用這種方法
  • 實現(xiàn)Runnable接口

    • 好處是:即使自己定義的線程類有了父類也沒關系,因為有了父類也可以實現(xiàn)接口,而且接口是可以多實現(xiàn)的
    • 弊端是:不能直接使用Thread中的方法需要先獲取到線程對象后,才能得到Thread的方法,代碼復雜

24.08_多線程(匿名內(nèi)部類實現(xiàn)線程的兩種方式)(掌握)

  • 繼承Thread類

      new Thread() {                                                  //1,new 類(){}繼承這個類
          public void run() {                                         //2,重寫run方法
              for(int i = 0; i < 3000; i++) {                         //3,將要執(zhí)行的代碼,寫在run方法中
                  System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
              }
          }
      }.start();
    
  • 實現(xiàn)Runnable接口

      new Thread(new Runnable(){                                      //1,new 接口(){}實現(xiàn)這個接口
          public void run() {                                         //2,重寫run方法
              for(int i = 0; i < 3000; i++) {                         //3,將要執(zhí)行的代碼,寫在run方法中
                  System.out.println("bb");
              }
          }
      }).start(); 
    

24.09_多線程(獲取名字和設置名字)(掌握)

  • 1.獲取名字
    • 通過getName()方法獲取線程對象的名字
    • 線程對象 有默認的名稱福压,命名方式: Thread-n 或 main
  • 2.設置名字
    • 通過構造函數(shù)可以傳入String類型的名字
    •   new Thread("xxx") {
            public void run() {
                for(int i = 0; i < 1000; i++) {
                    System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa");
                }
            }
        }.start();
        
        new Thread("yyy") {
            public void run() {
                for(int i = 0; i < 1000; i++) {
                    System.out.println(this.getName() + "....bb");
                }
            }
        }.start(); 
      
    • 通過setName(String)方法可以設置線程對象的名字
    •   Thread t1 = new Thread() {
            public void run() {
                for(int i = 0; i < 1000; i++) {
                    System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa");
                }
            }
        };
        
        Thread t2 = new Thread() {
            public void run() {
                for(int i = 0; i < 1000; i++) {
                    System.out.println(this.getName() + "....bb");
                }
            }
        };
        t1.setName("芙蓉姐姐");
        t2.setName("鳳姐");
        
        t1.start();
        t2.start();
      

24.10_多線程(獲取當前線程的對象)(掌握)

  • Thread.currentThread(), 主線程也可以獲取
    •   new Thread(new Runnable() {
            public void run() {
                for(int i = 0; i < 1000; i++) {
                    System.out.println(Thread.currentThread().getName() + "...aaaaaaaaaaaaaaaaaaaaa");
                }
            }
        }).start();
        
        new Thread(new Runnable() {
            public void run() {
                for(int i = 0; i < 1000; i++) {
                    System.out.println(Thread.currentThread().getName() + "...bb");
                }
            }
        }).start();
        Thread.currentThread().setName("我是主線程");                    //獲取主函數(shù)線程的引用,并改名字
        System.out.println(Thread.currentThread().getName());       //獲取主函數(shù)線程的引用,并獲取名字
      

24.11_多線程(休眠線程)(掌握)

  • Thread.sleep(毫秒,納秒), 控制當前線程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000納秒 1000000000

          new Thread() {
              public void run() {
                  for(int i = 0; i < 10; i++) {
                      System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
                      try {
                          Thread.sleep(10);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }.start();
          
          new Thread() {
              public void run() {
                  for(int i = 0; i < 10; i++) {
                      System.out.println(getName() + "...bb");
                      try {
                          Thread.sleep(10);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }.start();
    

24.12_多線程(守護線程)(掌握)

  • setDaemon(boolean), 設置一個線程為守護線程, 該線程不會單獨執(zhí)行, 當其他非守護線程都執(zhí)行結束后, 自動退出【守護線程 也可以守護 main線程】
    •   Thread t1 = new Thread() {
            public void run() {
                for(int i = 0; i < 50; i++) {
                    System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        
        Thread t2 = new Thread() {
            public void run() {
                for(int i = 0; i < 5; i++) {
                    System.out.println(getName() + "...bb");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        
        t1.setDaemon(true);                     //將t1設置為守護線程
        
        t1.start();
        t2.start();
      

24.13_多線程(加入線程)(掌握)

  • join(), 當前線程暫停, 等待指定的線程執(zhí)行結束后, 當前線程再繼續(xù)
  • join(int), 可以等待指定的毫秒之后繼續(xù)
    •   final Thread t1 = new Thread() {
            public void run() {
                for(int i = 0; i < 50; i++) {
                    System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        
        Thread t2 = new Thread() {
            public void run() {
                for(int i = 0; i < 50; i++) {
                    if(i == 2) {
                        try {
                            t1.join();  //插隊,加入
                            //t1.join(30);  //加入,有固定的時間,過了固定時間,繼續(xù)交替執(zhí)行
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(getName() + "...bb");
                }
            }
        };
        
        t1.start();
        t2.start();
      

24.14_多線程(禮讓線程)(了解)

  • yield()讓出cpu
  • 建議性的

24.15_多線程(設置線程的優(yōu)先級)(了解)

  • setPriority(int)設置線程的優(yōu)先級掏秩,參數(shù)越大優(yōu)先級越高。
  • 優(yōu)先級取值 1 到 10 荆姆,數(shù)值越大蒙幻,優(yōu)先級越高
  • 建議性的

24.16_多線程(同步代碼塊)(掌握)

  • 1.什么情況下需要同步
    • 當多線程并發(fā), 有多段代碼同時執(zhí)行時, 我們希望某一段代碼執(zhí)行的過程中CPU不要切換到其他線程工作. 這時就需要同步.
    • 如果兩段代碼是同步的, 那么同一時間只能執(zhí)行一段, 在一段代碼沒執(zhí)行結束之前, 不會執(zhí)行另外一段代碼.
  • 2.同步代碼塊
    • 使用synchronized關鍵字加上一個鎖對象來定義一段代碼, 這就叫同步代碼塊

    • 多個同步代碼塊如果使用相同的鎖對象, 那么他們就是同步的

        class Printer {
            Demo d = new Demo();
            public static void print1() {
                //鎖對象可以是任意對象,但是被鎖的代碼需要保證是同一把鎖,不能用匿名對象
                synchronized(d){                
                    System.out.print("我");
                    System.out.print("要");
                    System.out.print("賺");
                    System.out.print("大");
                    System.out.print("錢");
                    System.out.print("\r\n");
                }
            }
      
            public static void print2() {   
                synchronized(d){    
                    System.out.print("努");
                    System.out.print("力");
                    System.out.print("學");
                    System.out.print("習");
                    System.out.print("\r\n");
                }
            }
        }
      

24.17_多線程(同步方法)(掌握)

  • 使用synchronized關鍵字修飾一個方法, 該方法中所有的代碼都是同步的

      class Printer {
          public static void print1() {
              //鎖對象可以是任意對象,但是被鎖的代碼需要保證是同一把鎖,不能用匿名對象
              synchronized(Printer.class){        
                  System.out.print("I");
                  System.out.print("T");
                  System.out.print("程");
                  System.out.print("序");
                  System.out.print("員");
                  System.out.print("\r\n");
              }
          }
          /*
           * 非靜態(tài)同步函數(shù)的鎖是:this
           * 靜態(tài)的同步函數(shù)的鎖是:字節(jié)碼對象
           */
          public static synchronized void print2() {  
              System.out.print("杰");
              System.out.print("普");
              System.out.print("軟");
              System.out.print("件");
              System.out.print("\r\n");
          }
      }
    

24.18_多線程(線程安全問題)(掌握)

  • 多線程并發(fā)操作同一數(shù)據(jù)時, 就有可能出現(xiàn)線程安全問題

  • 使用同步技術可以解決這種問題, 把操作數(shù)據(jù)的代碼進行同步, 不要多個線程一起操作

          public class Demo2_Synchronized {
    
              /**
               * @param args
               * 需求:鐵路售票,一共100張,通過四個窗口賣完.
               */
              public static void main(String[] args) {
                  TicketsSeller t1 = new TicketsSeller();
                  TicketsSeller t2 = new TicketsSeller();
                  TicketsSeller t3 = new TicketsSeller();
                  TicketsSeller t4 = new TicketsSeller();
                  
                  t1.setName("窗口1");
                  t2.setName("窗口2");
                  t3.setName("窗口3");
                  t4.setName("窗口4");
                  t1.start();
                  t2.start();
                  t3.start();
                  t4.start();
              }
          
          }
          
          class TicketsSeller extends Thread {
              private static int tickets = 100;
              static Object obj = new Object();
              public TicketsSeller() {
                  super();
              }
              public TicketsSeller(String name) {
                  super(name);
              }
              public void run() {
                  while(true) {
                      synchronized(obj) {
                          if(tickets <= 0) 
                              break;
                          try {
                              Thread.sleep(10);//線程1睡,線程2睡,線程3睡,線程4睡
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println(getName() + "...這是第" + tickets-- + "號票");
                      }
                  }
              }
          }
    

24.19_多線程(火車站賣票的例子用實現(xiàn)Runnable接口)(掌握)

  • 作業(yè)

24.20_多線程(死鎖)(了解)

  • 多線程同步的時候, 如果同步代碼嵌套, 使用相同鎖, 就有可能出現(xiàn)死鎖
    • 盡量不要嵌套使用

        private static String s1 = "筷子左";
        private static String s2 = "筷子右";
        public static void main(String[] args) {
            new Thread() {
                public void run() {
                    while(true) {
                        synchronized(s1) {
                            System.out.println(getName() + "...拿到" + s1 + "等待" + s2);
                            synchronized(s2) {
                                System.out.println(getName() + "...拿到" + s2 + "開吃");
                            }
                        }
                    }
                }
            }.start();
            
            new Thread() {
                public void run() {
                    while(true) {
                        synchronized(s2) {
                            System.out.println(getName() + "...拿到" + s2 + "等待" + s1);
                            synchronized(s1) {
                                System.out.println(getName() + "...拿到" + s1 + "開吃");
                            }
                        }
                    }
                }
            }.start();
        }
      

24.21_多線程(以前的線程安全的類回顧)(掌握)

  • A:回顧以前說過的線程安全問題
    • 看源碼:Vector,StringBuffer,Hashtable Collections.synchroinzedXxx(xxx)
    • Vector是線程安全的,ArrayList是線程不安全的
    • StringBuffer是線程安全的,StringBuilder是線程不安全的
    • Hashtable是線程安全的,HashMap是線程不安全的

25.01_多線程(兩個線程間的通信)(掌握)

  • 1.什么時候需要通信
    • 多個線程并發(fā)執(zhí)行時, 在默認情況下CPU是隨機切換線程的
    • 如果我們希望他們有規(guī)律的執(zhí)行, 就可以使用通信, 例如每個線程執(zhí)行一次打印
  • 2.怎么通信
    • 如果希望線程等待, 就調用wait()【先釋放鎖,再阻塞】
    • 如果希望喚醒等待的線程, 就調用notify();【被喚醒胆筒,先轉入運行邮破,再競爭鎖,獲取鎖以后仆救,才可以往下運行】
    • 這兩個方法必須在同步代碼中執(zhí)行, 并且使用【同步鎖對象】來調用

25.02_多線程(三個或三個以上間的線程通信)

  • 多個線程通信的問題
    • notify()方法是隨機喚醒一個線程
    • notifyAll()方法是喚醒所有線程
    • JDK5之前無法喚醒指定的一個線程
    • 如果多個線程之間通信, 需要使用notifyAll()通知所有線程, 用while來反復判斷條件
  • 在同步代碼塊中抒和,使用哪個對象鎖,就使用該對象調用wait方法
  • 為什么wait方法和notify方法定義在Object類中彤蔽?
    • 我們使用鎖對象調用上述方法摧莽,而鎖對象可以是任意對象,所以定義到Object類中
  • sleep方法和wait方法有什么區(qū)別顿痪?
    • sleep方法必須傳入?yún)?shù)值镊辕,即一個時間值油够,時間到了自動醒來
    • wait方法中參數(shù)可有可無,有參表示過了參數(shù)時間后進入等待征懈,否則直接等待
    • sleep方法在同步函數(shù)或同步代碼塊中石咬,不釋放鎖
    • wait方法在同步函數(shù)或同步代碼塊中,釋放鎖

25.03_多線程(JDK1.5的新特性互斥鎖)(掌握)

  • 1.同步
    • 使用ReentrantLock類的lock()和unlock()方法進行同步
    • 類似synchronized
  • 2.通信
    • 使用ReentrantLock類的newCondition()方法可以獲取Condition對象
    • 需要等待的時候使用Condition的await()方法, 喚醒的時候用signal()方法
    • 不同的線程使用不同的Condition, 這樣就能區(qū)分喚醒的時候找哪個線程了

25.04_多線程(線程組的概述和使用)(了解)

  • A:線程組概述

    • Java中使用ThreadGroup來表示線程組卖哎,它可以對一批線程進行分類管理鬼悠,Java允許程序直接對線程組進行控制。
    • 默認情況下亏娜,所有的線程都屬于【主線程組】
      • public final ThreadGroup getThreadGroup()//通過線程對象獲取他所屬于的組
      • public final String getName()//通過線程組對象獲取他組的名字
    • 我們也可以給線程設置分組
      • 1,ThreadGroup(String name) 創(chuàng)建線程組對象并給其賦值名字
      • 2,創(chuàng)建線程對象
      • 3,Thread(ThreadGroup group, Runnable target, String name)
      • 4,設置整組的優(yōu)先級或者守護線程
    • B:案例演示
      • 線程組的使用,默認是主線程組
  •   MyRunnable mr = new MyRunnable();
      Thread t1 = new Thread(mr, "張三");
      Thread t2 = new Thread(mr, "李四");
      //獲取線程組
      // 線程類里面的方法:public final ThreadGroup getThreadGroup()
      ThreadGroup tg1 = t1.getThreadGroup();
      ThreadGroup tg2 = t2.getThreadGroup();
      // 線程組里面的方法:public final String getName()
      String name1 = tg1.getName();
      String name2 = tg2.getName();
      System.out.println(name1);
      System.out.println(name2);
      // 通過結果我們知道了:線程默認情況下屬于main線程組
      // 通過下面的測試焕窝,你應該能夠看到,默任情況下维贺,所有的線程都屬于同一個組
      System.out.println(Thread.currentThread().getThreadGroup().getName());
    
    • 自己設定線程組
  •   // ThreadGroup(String name)
      ThreadGroup tg = new ThreadGroup("這是一個新的組");
    
      MyRunnable mr = new MyRunnable();
      // Thread(ThreadGroup group, Runnable target, String name)
      Thread t1 = new Thread(tg, mr, "張三");
      Thread t2 = new Thread(tg, mr, "李四");
      
      System.out.println(t1.getThreadGroup().getName());
      System.out.println(t2.getThreadGroup().getName());
      
      //通過組名稱設置后臺線程袜啃,表示該組的線程都是后臺線程
      tg.setDaemon(true);
    

25.05_多線程(線程的五種狀態(tài))(掌握)

  • 看圖說話
  • 新建,就緒,運行,阻塞,死亡

25.06_多線程(線程池的概述和使用)(了解)

  • A:線程池概述
    • 程序啟動一個新線程成本是比較高的,因為它涉及到要與操作系統(tǒng)進行交互幸缕。而使用線程池可以很好的提高性能群发,尤其是當程序中要創(chuàng)建大量生存期很短的線程時,更應該考慮使用線程池发乔。線程池里的每一個線程代碼結束后熟妓,并不會死亡,而是再次回到線程池中成為空閑狀態(tài)栏尚,等待下一個對象來使用起愈。在JDK5之前,我們必須手動實現(xiàn)自己的線程池译仗,從JDK5開始抬虽,Java內(nèi)置支持線程池
  • B:內(nèi)置線程池的使用概述
    • JDK5新增了一個Executors工廠類來產(chǎn)生線程池,有如下幾個方法
      • public static ExecutorService newFixedThreadPool(int nThreads)
      • public static ExecutorService newSingleThreadExecutor()
      • 這些方法的返回值是ExecutorService對象纵菌,該對象表示一個線程池阐污,可以執(zhí)行Runnable對象或者Callable對象代表的線程。它提供了如下方法
      • Future<?> submit(Runnable task)
      • <T> Future<T> submit(Callable<T> task)
    • 使用步驟:
      • 創(chuàng)建線程池對象
      • 創(chuàng)建Runnable實例
      • 提交Runnable實例
      • 關閉線程池
    • C:案例演示
      • 提交的是Runnable
  •   // public static ExecutorService newFixedThreadPool(int nThreads)
      ExecutorService pool = Executors.newFixedThreadPool(2);
    
      // 可以執(zhí)行Runnable對象或者Callable對象代表的線程
      pool.submit(new MyRunnable());
      pool.submit(new MyRunnable());
    
      //結束線程池
      pool.shutdown();
    

25.07_多線程(多線程程序實現(xiàn)的方式3)(了解)

  • 提交的是Callable
  •   // 創(chuàng)建線程池對象
      ExecutorService pool = Executors.newFixedThreadPool(2);
    
      // 可以執(zhí)行Runnable對象或者Callable對象代表的線程
      Future<Integer> f1 = pool.submit(new MyCallable(100));
      Future<Integer> f2 = pool.submit(new MyCallable(200));
    
      // V get()
      Integer i1 = f1.get();
      Integer i2 = f2.get();
    
      System.out.println(i1);
      System.out.println(i2);
    
      // 結束
      pool.shutdown();
    
      public class MyCallable implements Callable<Integer> {
    
          private int number;
      
          public MyCallable(int number) {
              this.number = number;
          }
      
          @Override
          public Integer call() throws Exception {
              int sum = 0;
              for (int x = 1; x <= number; x++) {
                  sum += x;
              }
              return sum;
          }
      
      }
    
  • 多線程程序實現(xiàn)的方式3的好處和弊端
    • 好處:

      • 可以有返回值
      • 可以拋出異常
    • 弊端:

      • 代碼比較復雜咱圆,所以一般不用

25.08_設計模式(簡單工廠模式概述和使用)(了解)

  • A:簡單工廠模式概述
    • 又叫靜態(tài)工廠方法模式笛辟,它定義一個具體的工廠類負責創(chuàng)建一些類的實例
  • B:優(yōu)點
    • 客戶端不需要在負責對象的創(chuàng)建,從而明確了各個類的職責
  • C:缺點
    • 這個靜態(tài)工廠類負責所有對象的創(chuàng)建序苏,如果有新的對象增加手幢,或者某些對象的創(chuàng)建方式不同,就需要不斷的修改工廠類忱详,不利于后期的維護
  • D:案例演示
    • 動物抽象類:public abstract Animal { public abstract void eat(); }
    • 具體狗類:public class Dog extends Animal {}
    • 具體貓類:public class Cat extends Animal {}
    • 開始围来,在測試類中每個具體的內(nèi)容自己創(chuàng)建對象,但是,創(chuàng)建對象的工作如果比較麻煩监透,就需要有人專門做這個事情钦铁,所以就知道了一個專門的類來創(chuà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 animalName) {
              if(“dog”.equals(animalName)) {}
              else if(“cat”.equals(animale)) {
      
              }else {
                  return null;
              }
          }
      } 
    

25.09_設計模式(工廠方法模式的概述和使用)(了解)

  • A:工廠方法模式概述
    • 工廠方法模式中抽象工廠類負責定義創(chuàng)建對象的接口才漆,具體對象的創(chuàng)建工作由繼承抽象工廠的具體類實現(xiàn)。
    • 普通工廠模式【一個方法生產(chǎn)多種對象】
    • 多個工廠模式【多個方法各自生產(chǎn)對象】
    • 靜態(tài)工廠模式【方法設置static】
    • 抽象工廠模式【將工廠抽象得到 抽象工廠基類】
  • B:抽象工廠模式優(yōu)點
    • 客戶端不需要在負責對象的創(chuàng)建佛点,從而明確了各個類的職責醇滥,如果有新的對象增加,只需要增加一個具體的類和具體的工廠類即可超营,不影響已有的代碼鸳玩,后期維護容易,增強了系統(tǒng)的擴展性
  • C:缺點
    • 需要額外的編寫代碼演闭,增加了工作量
  • D:案例演示
  •   動物抽象類:public abstract Animal { public abstract void eat(); }
      工廠接口:public interface Factory {public abstract Animal createAnimal();}
      具體狗類:public class Dog extends Animal {}
      具體貓類:public class Cat extends Animal {}
      開始不跟,在測試類中每個具體的內(nèi)容自己創(chuàng)建對象,但是米碰,創(chuàng)建對象的工作如果比較麻煩窝革,就需要有人專門做這個事情,所以就知道了一個專門的類來創(chuàng)建對象吕座。發(fā)現(xiàn)每次修改代碼太麻煩虐译,用工廠方法改進,針對每一個具體的實現(xiàn)提供一個具體工廠吴趴。
      狗工廠:public class DogFactory implements Factory {
          public Animal createAnimal() {…}
              }
      貓工廠:public class CatFactory implements Factory {
          public Animal createAnimal() {…}
              }  
    

25.10_多線程(單例設計模式)(掌握)

  • 單例設計模式:保證類在內(nèi)存中只有一個對象漆诽。

  • 如何保證類在內(nèi)存中只有一個對象呢?

    • (1)控制類的創(chuàng)建锣枝,不讓其他類來創(chuàng)建本類的對象厢拭。private
    • (2)在本類中定義一個本類的對象。Singleton s;
    • (3)提供公共的訪問方式撇叁。 public static Singleton getInstance(){return s}
  • 單例寫法兩種:

    • (1)餓漢式 開發(fā)用這種方式供鸠。
    •   //餓漢式
        class Singleton {
            //1,私有構造函數(shù)
            private Singleton(){}
            //2,創(chuàng)建本類對象
            private static Singleton s = new Singleton();
            //3,對外提供公共的訪問方法
            public static Singleton getInstance() {
                return s;
            }
            
            public static void print() {
                System.out.println("11111111111");
            }
        }
      
    • (2)懶漢式 面試寫這種方式。多線程的問題陨闹?
    •   //懶漢式,單例的延遲加載模式
        class Singleton {
            //1,私有構造函數(shù)
            private Singleton(){}
            //2,聲明一個本類的引用
            private static Singleton s;
            //3,對外提供公共的訪問方法
            public static Singleton getInstance() {
                if(s == null)
                    //線程1,線程2
                    s = new Singleton();
                return s;
            }
            
            public static void print() {
                System.out.println("11111111111");
            }
        }
      
    • (3)第三種格式
    •   class Singleton {
            private Singleton() {}
        
            public static final Singleton s = new Singleton();//final是最終的意思,被final修飾的變量不可以被更改
        }
      

25.11_多線程(Runtime類)

  • Runtime類是一個單例類
    •   Runtime r = Runtime.getRuntime();
        //r.exec("shutdown -s -t 300");     //300秒后關機
        r.exec("shutdown -a");              //取消關機
      

25.12_多線程(Timer)(掌握)

  • Timer類:計時器

          public class Demo5_Timer {
              /**
               * @param args
               * 計時器
               * @throws InterruptedException 
               */
              public static void main(String[] args) throws InterruptedException {
                  Timer t = new Timer();
                  t.schedule(new MyTimerTask(), new Date(114,9,15,10,54,20),3000);
                  
                  while(true) {
                      System.out.println(new Date());
                      Thread.sleep(1000);
                  }
              }
          }
          class MyTimerTask extends TimerTask {
              @Override
              public void run() {
                  System.out.println("起床背英語單詞");
              }
              
          }
    

25.13_GUI(如何創(chuàng)建一個窗口并顯示)

  • Graphical User Interface(圖形用戶接口)回季。
  •   Frame  f = new Frame(“my window”);
      f.setLayout(new FlowLayout());//設置布局管理器
      f.setSize(500,400);//設置窗體大小
      f.setLocation(300,200);//設置窗體出現(xiàn)在屏幕的位置
      f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));
      f.setVisible(true);
    

25.14_GUI(布局管理器)

  • FlowLayout(流式布局管理器)
    • 從左到右的順序排列。
    • Panel默認的布局管理器正林。
  • BorderLayout(邊界布局管理器)
    • 東泡一,南,西觅廓,北鼻忠,中(填充所有)
    • Frame默認的布局管理器。
  • GridLayout(網(wǎng)格布局管理器)
    • 規(guī)則的矩陣
  • CardLayout(卡片布局管理器)
    • 選項卡eclipse編輯區(qū)
  • GridBagLayout(網(wǎng)格包布局管理器)
    • 非規(guī)則的矩陣(計算器應用)

25.15_GUI(窗體監(jiān)聽)

Frame f = new Frame("我的窗體");
//事件源是窗體,把監(jiān)聽器注冊到事件源上
//事件對象傳遞給監(jiān)聽器
f.addWindowListener(new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
                     //退出虛擬機,關閉窗口
        System.exit(0);
    }
});

25.16_GUI(鼠標監(jiān)聽)

  • 組件.addMouseListener(new MouseAdapter(){ 重寫方法; });

25.17_GUI(鍵盤監(jiān)聽和鍵盤事件)

  • 組件.addKeyListener();
  • KeyEvent: getKeyCode() VK_SPACE

25.18_GUI(動作監(jiān)聽)

  • 默認就是空格鍵 鼠標左鍵
  • 應用場景: 點擊左鍵、空格 視頻暫停播放
  • 組件.addActionListener(new ActionListener(){ ... });

25.19_設計模式(適配器設計模式)(掌握)

  • a.什么是適配器
    • 在使用監(jiān)聽器的時候, 需要定義一個類事件監(jiān)聽器接口.
    • 通常接口中有多個方法, 而程序中不一定所有的都用到, 但又必須重寫, 這很繁瑣.
    • 適配器簡化了這些操作, 我們定義監(jiān)聽器時只要繼承適配器, 然后重寫需要的方法即可.
  • b.適配器原理
    • 適配器就是一個類, 實現(xiàn)了監(jiān)聽器接口, 所有抽象方法都重寫了, 但是方法全是空的.
    • 適配器類需要定義成抽象的,因為創(chuàng)建該類對象,調用空方法是沒有意義的
    • 目的就是為了簡化程序員的操作, 定義監(jiān)聽器時繼承適配器, 只重寫需要的方法就可以了.

25.20_GUI(需要知道的)

  • 事件處理
    • 事件: 用戶的一個操作
    • 事件源: 被操作的組件
    • 監(jiān)聽器: 一個自定義類的對象, 實現(xiàn)了監(jiān)聽器接口, 包含事件處理方法,把監(jiān)聽器添加在事件源上, 當事件發(fā)生的時候虛擬機就會自動調用監(jiān)聽器中的事件處理方法

25.21_day25總結

把今天的知識點總結一遍帖蔓。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矮瘟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子塑娇,更是在濱河造成了極大的恐慌澈侠,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埋酬,死亡現(xiàn)場離奇詭異哨啃,居然都是意外死亡,警方通過查閱死者的電腦和手機写妥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門拳球,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人珍特,你說我怎么就攤上這事祝峻。” “怎么了扎筒?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵莱找,是天一觀的道長。 經(jīng)常有香客問我嗜桌,道長宋距,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任症脂,我火速辦了婚禮谚赎,結果婚禮上右蕊,老公的妹妹穿的比我還像新娘憎妙。我一直安慰自己,他們只是感情好类嗤,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布棕所。 她就那樣靜靜地躺著闸盔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琳省。 梳的紋絲不亂的頭發(fā)上迎吵,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音针贬,去河邊找鬼击费。 笑死,一個胖子當著我的面吹牛桦他,可吹牛的內(nèi)容都是我干的蔫巩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼圆仔!你這毒婦竟也來了垃瞧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤坪郭,失蹤者是張志新(化名)和其女友劉穎个从,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歪沃,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡嗦锐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了绸罗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡豆瘫,死狀恐怖珊蟀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情外驱,我是刑警寧澤育灸,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站昵宇,受9級特大地震影響磅崭,放射性物質發(fā)生泄漏。R本人自食惡果不足惜瓦哎,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一砸喻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒋譬,春花似錦割岛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剂买,卻和暖如春惠爽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞬哼。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工婚肆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坐慰。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓旬痹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子两残,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

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

  • 文章來源:http://www.54tianzhisheng.cn/2017/06/04/Java-Thread/...
    beneke閱讀 1,483評論 0 1
  • 一永毅、基礎知識:1、JVM人弓、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機...
    殺小賊閱讀 2,378評論 0 4
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,957評論 1 18
  • 本文主要講了java中多線程的使用方法沼死、線程同步、線程數(shù)據(jù)傳遞崔赌、線程狀態(tài)及相應的一些線程函數(shù)用法意蛀、概述等。 首先講...
    李欣陽閱讀 2,454評論 1 15
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機制的簡單原理和應用健芭。 當JAVA程序違反了JA...
    八爺君閱讀 4,591評論 1 114