爆肝!!!!JavaSE知識點1.3w字總結

爆肝!!!!JavaSE知識點1.3w字總結

Java基礎語法知識

關鍵名詞

jdk

jdk(java development kit),即Java開發工具集。java

  • SUN公司爲JDK工具包提供了一整套文檔資料,咱們習慣上稱
    之爲JDK文檔。
  • JDK文檔中提供了Java中的各類技術的詳細資料,以及JDK中提
    供的各類類的幫助說明 。
  • JDK文檔是Java語言的完整說明,大多數書籍中的類的介紹都
    要參照它來完成,它是編程者常常查閱的資料。

jre

jre(java runtime enviroment),即Java運行環境編程

jvm

jvm(java virtual machine),Java虛擬機。目前主要使用的式hotsopt。小程序

Java歷史

sun公司

  • 美國SUN(Stanford University Network)公司
  • 在中國大陸的正式中文名爲「太陽計算機系統(中國)有限公司」
  • 在臺灣中文名爲「升 陽電腦公司」。

Java爲何被髮明

  • Green項目設計模式

  • 應用環境:像電視盒這樣的消費類電子產品數組

  • 要求:安全

    • 語言自己是中立的,也就是跨平臺
  • 發明者:James Gosling服務器

  • 歷程:網絡

▪ 1991年,Sun公司的Green項目,Oak
▪ 1995年,推出Java測試版
▪ 1996年,JDK1.0
▪ 1997年,JDK1.1
▪ 1998年,JDK1.2,大大改進了早期版本的缺陷,是一個革命性的版本,改名爲Java2
▪ 1999 Java被分紅J2SE、J2EE 和J2ME,JSP/Servlet技術誕生
▪ 2004年,J2SE 5.0 (1.5.0) Tiger老虎.爲了表示這個版本的重要性,J2SE1.5改名爲J2SE5.0。
▪ 2006年,J2SE 6.0 (1.6.0) Mustang野馬.此時,Java的各類版本被改名,取消其中的數字"2":J2EE改名爲Java EE, J2SE改名爲
Java SE,J2ME改名爲Java ME
▪ 2009年4月20日甲骨文收購Sun公司,交易價格達74億美圓
▪ 2011年,JavaSE7.0
▪ 2014年 ,JavaSE8.0
▪ 2017年,JavaSE9.0
▪ 2018年3月,JavaSE10.0
▪ 2018年9月,JavaSE11.0
▪ 2019年3月,JavaSE12.0數據結構

第一個Java程序

public class Test{
    public static void main(String[] args){
        System.out.println("hello, world");
    }
}

標識符

定義

用來給類、變量、方法、對象等起的名稱。由於在Java中一切皆對象,故不存在函數這一說,只有方法多線程

規則

  • 首字母能夠是字母、下劃線、美圓符號,可是不能是數字

    • // 合法
      int a; 
      int _a;
      int A;
      int $a;
      // 不合法
      int 1a;
  • 其餘部分只能是字母、下劃線、數字、美圓符號

    • // 合法
      int a1_$;
      // 不合法
      int a-1;
  • Java嚴格區分大小寫

    • int a;
      int A;
      // a和A不是同一個變量
  • Java命名變量的時候建議採用駝峯標識以及變量要見名知意

    • // 建議
      String name;
      int age;
      boolean isAlive;
      // 不建議
      String s;
      int a;
      boolean b;

保留字

定義

給系統使用的關鍵字,好比:int,float,void, class,for,while,break等等,在定義變量的時候不能定義成:int float;

運算符

算術運算符

算術運算符包括:+,-,*,/,%。

int a = 10;
int b = 3;
a + b; // 13
a - b; // 7
a * b; // 30
a / b; // 做商, 3
a % b; // 取餘, 1

比較運算符

比較運算符包括:==,!=,>,>=,<, <=。

int a = 10;
int b = 3;
a == b; // false
a != b; // true
a > b ; // true
a >= b; // true
a < b ; // false
a <= b; // false

賦值運算符

賦值運算符:int a = 10;,將10賦值給變量a。

邏輯運算符

邏輯運算符包括:&&,||,!。

int a = 10;
int b = 1;
int c = 2;
// && 兩邊同時爲true結果返回true,不然返回false
(a > b) && (a > c); // true,a>b爲true,a>c爲true
(a > b) && (a < c); // false, 由於,a>b爲true,a<c爲fasle
// || 兩邊只要有一邊爲true,結果返回true
(a > b) || (a > c); // true,a>b爲true,a>c爲true
(a > b) || (a < c); // true,a>b爲true,a<c爲false
(a < b) || (a > c); // true,a<b爲false,a>c爲true
(a < b) || (a < c); // false,a<b爲fasle,a<c爲false
// !,對取得的布爾值取反操做,!true->false, !false->true
!(a>c); // fasle,a>c爲true

// &&,|| 的短路操做
(a > b) && ((c = b) ==b); // true,c=1,由於a>b爲true,繼續比較右邊,執行右邊
(a < b) && ((c=b)==b); // false,c=2,由於a<b爲false,直接返回false,不比較後面代碼,也不執行後面代碼
(a > b) || ((c=b)==b); // true,c=2,由於a>b爲true,直接返回結果,不執行後面操做
(a < b) || ((c=b)==b); // true,c=1,由於a<b爲false,繼續比較右邊,執行右邊代碼,右邊結果爲true

三目運算符

形如:xxx?x:y。若xxx語句的返回值爲true,則返回x,不然返回y。

int a = 10>20?1:2; // a=2,由於10>20爲false

位運算符

位運算符主要包括:&,|,^。

// & 將兩個數轉換爲二進制進行比較,相同的位上都是1,則該位比較後的值爲1
// | 將兩個數轉換爲二進制進行比較,相同的位上若是存在1,則該位比較後的值爲1
// ^ 將兩個數轉換爲二進制進行比較,相同的位上若是存在1,且不一樣時爲1,則該位比較後的值爲1

5轉換成二進制:0101
3轉換成二進制:0011
	0101
  & 0011
  = 0001 轉換成10進制:1
	0101
  | 0011
  = 0111 轉換成10進制:7
	0101
  ^ 0011
  = 0110 轉換成10進制:6

數據類型

基本數據類型

byte b;
short s;
int i;
long l;
float f;
double d;
char c;
boolean b;
String string;
整型
  • byte,佔1個字節,值得範圍是:- 128~127
  • short,佔2個字節,值得範圍是:-65536~65535
  • int,佔4個字節,值得範圍是:-4294967296~4294967295
  • long,佔8個字節,值得範圍是:-18446744073709551616~18446744073709551615
浮點型
  • float,佔4個字節,值的範圍是:1.4E-45~3.4028235E38
  • double,佔8個字節,值的範圍是:4.9E-324~1.7976931348623157E308
字符型
  • char,佔2個字節
布爾型

佔1位。

  • true
  • false

引用數據類型

  • String

  • 數組

    • 定義方式

      • int[] numbers = new int[10];
      • int[] numbers = new int[10]{1,2,3,4,5,6,7,8,9,0};
      • int[] numbers = {1,2,3,4,5,6,7,8,9,0};
    • 使用

      • 獲取

        • int[] numbers = {1,2,3};
          System.out.println(numbers[1]);
      • 修改

        • int[] numbers = {1,2,3};
          numbers[1] = 10;
    • 注意:

      • 數組的下標爲:0~數組的長度-1
  • 對象

    • 類的實例化

      • class Person{
            
        }
        Person person = new Person();
        // person即爲對象
  • 接口

    • 某種行爲/功能的抽象,若要使用則要實現接口中的全部方法,接口相似於一種約束、規範

    • interface MyInterface{
          void method();
      }
  • 等等

流程控制語句

順序結構

從上到下依次按順序執行

分支結構

  • if

    if(條件){
        執行語句
    }
    // 但條件的返回結果爲true時執行執行語句,不然不執行
    // 應用
    int a = 10;
    if(a < 20){
        a = 30;
    }
    // 由於 a<20爲true,執行語句,a=30
  • if...else

    if(條件){
        執行語句
    }else{
        執行語句2
    }   
    // 若條件的返回結果爲true,則執行語句,不然執行語句2
    // 應用
    int a = 10;
    if(a>10){
        a = 8;
    }else{
        a = 20;
    }
    // 由於a>10爲false,所以執行a=20
  • if...else if...else

    • if(條件1){
          執行語句1
      }else if(條件2){
          執行語句2
      }else{
          執行語句3
      }
      // 若知足條件1,則執行語句1,不然若知足條件2,則執行語句2,不然執行語句3
      // 應用
      int a = 10;
      if(a > 10){
          a = 8;
      }else if(a > 5){
          a = 4
      }else{
          a = 100;
      }
      //a = 4,由於a>10爲false,a>5爲false,執行a=4
  • switch

    switch(變量){
        case value1:
            執行語句1
            break;
        case value2:
            執行語句2
            break;
        default:
            執行語句3
            break;
    }
    // 變量的值若是等於某一個case後面的值則執行相應的語句,而後跳出語句,不然就執行default裏的語句,而後退出
    // 這裏變量以及case的值只能爲:整數、字符、字符串
    // 應用
    int a = 10;
    switch(a){
        case 10:
            System.out.println("10");
            break;
        case 20:
            System.out.println("20");
            break;
        default:
            System.out.println("no");
            break;
    }
    // 打印10

循環結構

  • do...while

    • do{
          執行語句
      }while(條件);
      // 循環執行語句,直到不知足條件,至少作一次
      int a = 0;
      do{
          System.out.print(i);
          i++;
      }while(i<20);
  • while

    while(條件){
        執行語句
    }
    // 但知足條件時循環執行語句,直到不知足條件
    int a = 0;
    while(a < 10){
        System.out.println(a);
        a++;
    }
  • for

    for(初始化變量;知足的條件;更新變量){
        執行語句
    }
    // 對於初始化變量,每次執行語句後更新變量,直到不知足條件
    for(int a;a<10;a++){
        System.out.println(a);
    }
  • 加強for循環

對於一個集合、數組或者map,若其中的元素的類型都一致,則可使用使用forech(加強for循環來遍歷)

for(類型 變量:集合){
    執行語句
}
// 應用
int[] numbers = {1,2,3,4,5};
for(int number:numbers){
    System.out.println(number);
}

流程控制語句的語法規則

  • break

    • 跳出當前循環

      for(int i=0;i<10;i++){
          if(i==5){
              break;
          }
          System.out.println(i);
      }
      //打印0-4後,更新變量,i=5,此時跳出for循環
  • continue

    • 跳過本次循環

      • for(int i=0;i<10;i++){
            if(i % 2 !=0){
                continue;
            }
            System.out.println(i);
        }
        // 打印0-9全部的偶數
  • return

    • 返回結果值

      • public int addOne(int number){
            return number + 1;
        }
        
        System.out.println(addOne(10));
        // 返回11
    • 結束程序

      • for(int i=0;i<10;i++){
            if(i ==5){
                return;
            }
        }
        
        // 當i==5時,結束程序

面向對象

編程思想

面向過程編程(POP, Procedure Oriented Programming)

典型的是C語言。經過分析出解決問題所須要的步驟,而後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就能夠了。以把大象放入冰箱爲例,咱們首先定義一個拿到大象的函數,而後定義一個開冰箱的函數,而後定義一個放大象的函數,而後定義一個關冰箱的函數,最後一次調用就能夠實現功能了。

在考慮問題時,以一個具體的流程(事務過程)爲單位,考慮它的實現。

面向對象編程(OOP,Object Oriented Programming)。

典型的C++、C#、Java等編程語言。經過將現實世界中的物體抽象成一個具體的類,經過調用類的相關方法來完成一系列行爲。仍是以把大象放入冰箱爲例,咱們先定義一我的的類,有拿大象、放大象、開冰箱、關冰箱的方法(也就是人能夠作這些事情),再定義一個大象類,再定義一個冰箱類,而後建立相應的對象調用相關的方法便可。

在考慮問題時,以對象爲單位,考慮它的屬性及方法。

面向接口編程(IOP,Interface Oriented Programming)

定義(規範,約束)與實現(名實分離的原則)的分離。

接口的自己反映了系統設計人員對系統的抽象理解。

面向切面編程(AOP,Aspect Oriented Programming)

經過預編譯方式和運行期間動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。

函數時編程(Function Programming)

典型的是Python、JavaScript語言。

函數式編程是種編程方式,它將電腦運算視爲函數的計算。函數編程語言最重要的基礎是λ演算(lambda calculus),並且λ演算的函數能夠接受函數看成輸入(參數)和輸出(返回值)。主要思想是把運算過程儘可能寫成一系列嵌套的函數調用。

類和對象

類是對象的抽象,對象是類的實例化

在現實生活中,人(Person)表示一種生物,很抽象,具體的人:張三,就是一個對象,一個具體的人,一個獨立的個體。

// 定義一個類
class Person{
    
}
// 實例化一個對象(建立一個對象)
Person zhangsan = new Person();
如何建立對應的對象

經過new關鍵字實現。

構造器

一個類的構造方法,用於對一個對象的初始化,好比說咱們在買電腦的時候都會選擇電腦的:cpu、內存、硬盤、顯示屏等等,這些至關於初始化。

class Computer{
    private String cpu; 
    private String arm;
    private String disk;
    private String screen;
    
    public Computer(String _cpu, String _arm, String _disk, String _screen){
        cpu = _cpu;
        arm = _arm;
        disk = _disk;
        screen = _screen;
    }
}
// 利用構造器建立對象
Computer myComputer = new Computer("Intel", "英偉達","sanxing", "英偉達");

默認狀況下建議寫一個無參構造器。

this

指代當前對象。能夠在構造方法中使用,用來區分參數和成員變量,在普通方法中使用表示調用當前的屬性或者當前類的方法,能夠省略。

class Computer{
    private String cpu; 
    private String arm;
    private String disk;
    private String screen;
    
    public Computer(String cpu, String arm, String disk, String screen){
        this.cpu = cpu;
        this.arm = arm;
        this.disk = disk;
        this.screen = screen;
    }
}
// 利用構造器建立對象
Computer myComputer = new Computer("Intel", "英偉達","sanxing", "英偉達");
static

表示靜態的,更準確的說是表示類的什麼什麼,被static修飾的方法、函數、類(內部類)在類加載的時候就建立了,而沒有被修飾的則是屬於對象,只有當建立對象的時候才建立,由於,static修飾的屬性、方法、類的建立是先於普通屬性、方法的,所以:靜態方法中不能存在普通的屬性、方法、對象。

被static修飾的屬性、方法,類能夠直接調用。

class Person{
    static boolean isPerson = true;
    
    static void sleep(){
        
    }
}
// 調用
System.out.println(Person.isPerson);
System.out.println(Person.sleep());
final

表示最終的,不可更改,有三種形式

  • 修飾在屬性上,表示屬性的值不可更改,若屬性的值是一個引用,則不能再被賦予其餘的引用,可是引用中的屬性能夠更改
  • 修飾在方法上,表示該方法不能被重寫(從新實現)
  • 修飾在類上,表示類不可被繼承
package

打包:區分同名的文件,分佈在不一樣的目錄。

將不一樣的功能代碼整合在一塊兒。

import

導包:方便引用其餘包的類

訪問修飾符

規定方法、類、屬性的訪問範圍。

分類:

  • private,只能當前類中使用
  • default,只能在當前包、類中使用
  • protected,能夠在本類、本包以及繼承該類的類中使用
  • public,同一個項目下的任何地方均可以使用
方法的重載

在同一個類中,能夠定義多個同名方法,可是,這些方法必須知足如下三個條件之一:

  • 參數類型不同

  • 參數個數不同

  • 參數順序不同

    class Demo{
        public void method(){
            
        }
        public void method(String str){
            
        }
        public void method(String str,int number){
            
        }
        public void method(int number,String name){
            
        }
    }

面向對象三大特性

封裝
廣義的封裝

在代碼中能夠將某個代碼塊變成方法,抽象出某些工具類

狹義的封裝
  1. 將屬性設置成私有,不能被外部直接訪問
  2. 提供共有的set和get方法,使外部能夠進行調用
  3. 能夠實現更加複雜細緻的內部邏輯判斷
  4. 保護類的內部實現細節,只提供公共的對外訪問接口,保護類的安全
public class Test2 {
    private String string;
    private int number;

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}
繼承
  • 解釋說明

    • 子類能夠擁有父類的某些屬性和方法,可是私有的除外
    • java中式嚴格意義上的單繼承
    • 使用extends關鍵字來實現繼承
  • 重寫

    • 當父類中的某些方法不能知足子類的須要的時候,子類能夠重寫父類的方法,要求跟父類的方法名稱一致
    • 子類方法的訪問修飾符>父類的訪問修飾符
    • 建議添加@override註解,在編譯時提示錯誤
  • super

    • 表示的是父類的對象
    • 在建立對象的時候,能夠在子類中直接經過super關鍵字調用父類的構造方法
    • 在子類方法中可使用super.的方法調用父類的方法和屬性
  • public class Test2 extends Test4{
        @Override
        public void method() {
            super.method1();
            System.out.println("Test2->method");
        }
        
    }
    
    class Test4{
        public void method(){
            System.out.println("Test4->method");
        }
        
        public void method1(){
            System.out.println("Test4->method1");
        }
    }
多態
  • 通俗解釋:對於同一個指令,不一樣的對象給予的不一樣反應
  • 前提
    1. 必須有繼承關係
    2. 子類必須重寫父類方法
    3. 父類引用指向子類對象
  • 父類和子類對象的轉換:
    • 子類到父類,自動轉換
    • 父類到子類,強制轉換,且經過inatanceof判斷
public class Test2{
    public static void main(String[] args) {
        personSpeak(new Boy()); // 傳入子類自動轉換成父類
        personSpeak(new Girl());
        personSpeak((Person) new Object()); // 父類到子類強制轉換,Object類是全部類的父類
    }
    
    static void personSpeak(Person person){
        person.speak();
    }
    

}

abstract class Person{
    abstract void speak();
}

class Boy extends Person{

    @Override
    void speak() { // 重寫父類方法
        System.out.println("男孩說話");
    }
}

class Girl extends Person{

    @Override
    void speak() {
        System.out.println("女孩說話");
    }
}
接口
  • 接口表明一種能力,實現接口,則表示具有了某種功能
  • 接口表明一種規範,在實現接口的時候必須遵循相應的規範,好比說從新實現方法的時候參數的要求、返回值的要求等等
  • 接口能夠在必定程度上實現java的多繼承,java只支持單繼承,但能夠實現多個接口,能夠變相的實現多繼承
  • 接口中的方法都是public abstract這樣的訪問修飾符,不能包含具體的方法實現
  • 子類若是實現了某個接口,那麼接口中的全部方法都要被重寫,且實現具體的邏輯,若是沒有實現的話,那麼子類要麼是子接口要麼是抽象類
  • 接口中的屬性都是常量值
public class Test2{
    public static void main(String[] args) {
        new Singer().singSong(new Boy());
    }
    

}

interface Sing{
    final boolean isSing = true;
    void singSong(Person person);
}


class Singer extends Person implements Sing{

    @Override
    public void singSong(Person person) {
        this.speak();
    }

    @Override
    void speak() {

    }
}
抽象類
  1. 抽象類跟接口相似,能夠定義抽象方法,也能夠包含具體的實現
  2. 抽象類和抽象方法須要使用abstract關鍵字來進行修飾
  3. 抽象類的子類必須重寫抽象類中的抽象方法,若是不重寫的話,那麼該子類也會成爲一個抽象類
  4. 抽象類更能表示多態,對於子類來講須要實現相同的功能且實現細節同樣的則公用方法,對於子類來講須要各自實現細節的就重寫方法
// 案例:人都要睡覺;人要說話,可是不一樣國家的人說的話不同,中國人說中文,美國人說美語
abstract class Person{
    
    public void sleep(){
        System.out.println("是我的都睡覺");
    }
    
    abstract void speak();
}

class Chinese extends Person{

    @Override
    void speak() {
        System.out.println("中國人說做文");
    }
}

class American extends Person{

    @Override
    void speak() {
        System.out.println("美國人說美語");
    }
}
內部類
  • 靜態內部類
  • 方法內部類
  • 匿名內部類
  • 成員內部類
public class Demo1 {

    public static void main(String[] args) {
        // 靜態內部類
        StaticInnerClass staticInnerClass = new Demo1.StaticInnerClass();
        // 成員內部類
        InnerClass innerClass = new Demo1().new InnerClass();
        // 方法內部類,生命週期指在方法內
        Object o = method();
        // 匿名內部類
        MyInterface myInterface = new MyInterface() {};
    }

    static class StaticInnerClass{

    }

    class InnerClass{

    }

    public static Object method(){
        class MethodInnerClass{

        }
        
        return new MethodInnerClass();
        
    }
}

interface MyInterface{
    
}

異常

定義

表示程序在運行過程當中出現的非正常狀況,編寫代碼的過程當中儘量少的減小異常出現的狀況

分類

  • Throwable
    • Error 代碼級別沒法解決的異常狀況
    • Exception
      • 運行時異常:在程序運行過程當中,因爲輸入的參數值的不一樣,可能會發生也可能不會發生
      • checked異常 :編譯時異常,在ide中會顯示的檢查出來

異常的處理

捕獲異常
  • try...catch

    try{
        可能出現異常的語句
    }catch(可能出現的異常){
        捕捉異常後執行的語句
    }
    // 
    try{
        int x = 1 /0;
    }catch(ArithmeticException e){
        e.printStack();
    }
  • try...catch...finally

    try{
        可能發生異常的代碼
    }catch(發生的異常){
        捕捉異常後執行的語句
    }finally{
        無論是否發生異常都要執行的語句
    }
    
    //
    try{
        int x = 1 /0;
    }catch(ArithmeticException e){
        e.printStack();
    }finally{
        System.out.println("finally")
    }
  • 注意

    1. 當發生異常時,在try代碼塊中異常語句後面的語句不會再執行

    2. try、catch、finally以及try...catch...finally以外的代碼是互相獨立的,在try中定義的變量在其餘的部分沒法訪問,改變了僅做用於try部分,其餘catch、finally狀況相似,可是外部定義的變量在try、catch、finally中可使用

    3. 在進行異常捕獲的時候,return語句的不一樣位置會形成結果的不一樣

      1. 首先討論try...catch...finally後面有代碼的狀況

        //此時注意一個關鍵的點:checked異常,即return語句後面不能再跟語句
        // 例如
        return;
        System.out.println("after return");// 這條語句ide直接報錯,至關於多餘的
        // 故return的語句只能有一下幾種狀況
        //1
                try{
                    System.out.println("1");
                    System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
                System.out.println("4");
            }
        // 此時return語句永遠都不會被執行,也就不會報錯。
        //2
                try{
                    System.out.println("1");
        //            System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
                System.out.println("4");
        //此時,當程序執行到return語句時,並不會當即執行,而是先掛起,等執行完finally中的語句以後再執行return語句結束程序,故try、catch、finally以外的其餘代碼不會再執行
        //其餘的catch、finally中都不能再存在return語句了
      2. try...catch...finally後面沒有代碼的狀況

        //第一種狀況
        try{
                    System.out.println("1");
                    System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
        // 此時return語句永遠不會執行
        // 第二種狀況,此時return語句有沒有都沒有關係
        try{
                    System.out.println("1");
        //            System.out.println(1 / 0);
                    return;
                }catch (Exception e){
                    System.out.println("2");
        //            return;
                }finally {
                    System.out.println("3");
        //            return;
                }
        //第三種狀況
        try{
                    System.out.println("1");
                    System.out.println(1 / 0);
        //            return;
                }catch (Exception e){
                    System.out.println("2");
                    return;
                }finally {
                    System.out.println("3");
        //            return;
                }
        //此時,仍是跟前面同樣的,return先掛起,執行完finally中的代碼後再結束程序
        //第三種狀況
        public class Demo {
            public static void main(String[] args) {
                System.out.println(method());
        
            }
        
            public static int method(){
                try{
                    System.out.println("1");
                    System.out.println(1 / 0);
        //            return;
                }catch (Exception e){
                    System.out.println("2");
                    return 1;
                }finally {
                    System.out.println("3");
        //            return 2;
                }
        //        System.out.println("4");
                return 0;
            }
        }
        // 此時會執行最近的return語句
      3. 綜上:

        1. return語句會被掛起,等執行完finally中的語句後再執行
        2. 當存在兩個return語句時且都能被執行時,優先執行finally中的return
拋出異常
throws

將異常狀況拋出給調用者

注意,若是整個程序的運行過程當中都沒有異常的處理的話,最終異常會拋給jvm,不太友好,通常都要對異常進行處理

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo1 {
    public static void main(String[] args) throws FileNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("test.txt");
    }
}

自定義異常

java中提供了很是多的異常類,可是在某些項目中須要本身定義獨特的異常處理方式,此時須要自定義異常

  1. 繼承Exception
  2. 編寫構造方法,能夠傳入本身想打印的異常信息
  3. 調用的時候經過throw向外拋出異常
public class MyException extends Exception{
    public MyException(){
        System.out.println("自定義異常");
    }
}
public class Demo1 {
    public static void main(String[] args) throws MyException {
        throw new MyException();
    }
}

另外,還能夠自定義異常信息

public class Demo1 {
    public static void main(String[] args) throws Exception {
        throw new Exception("test");
    }
}

經常使用類

包裝類

  1. 基本數據類型都由對應的包裝類

    • int:Integer
    • byte:Byte
    • short:Short
    • long:Long
    • float:Float
    • double:Double
  2. 自動拆箱和自動裝箱

  3. 舉例

    public class Demo {
        public static void main(String[] args) {
            // 此時自動調用:Integer.valueOf(),若數字大於-128且小於127,直接返回值,不然新建一個對象
            Integer integer1 = 1000;
            Integer integer2 = 1000;
            int i1 = 1000;
            int i2 = 1000;
            System.out.println(integer1 == integer2); // 由於兩個變量不是同一個對象所以結果爲false
            System.out.println(integer1.equals(integer2));// true
            System.out.println(i1 == i2); // true
            System.out.println(i1 == integer2); // true
        }
    }

String

  • 不可變字符串:String

  • 可變字符串:

    • 線程安全:StringBuffer
    • 線程不安全:StringBuilder
  • 舉例

    public class Demo1 {
        public static void main(String[] args) {
            StringBuffer stringBuffer = new StringBuffer("hello,world");
            // 增
            stringBuffer.insert(0, "@");
            stringBuffer.append("#");
            // 刪
            stringBuffer.delete(0,1);
            // 改
            stringBuffer.setCharAt(0, '$');
            stringBuffer.replace(0,1,"x");
            // 查
            stringBuffer.indexOf("a");
            stringBuffer.substring(0,1);
            System.out.println(stringBuffer);
    
    
        }
    }

Date

日期經常使用類

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo2 {
    public static void main(String[] args) {
        DateFormat dateFormat = new SimpleDateFormat("YY-MM-dd HH-mm-ss"); // 建立格式化日期類
        System.out.println(dateFormat.format(new Date()));
    }
}

Calender

返回格林威治時間

import java.util.Calendar;
import java.util.GregorianCalendar;

public class Demo3 {
    public static void main(String[] args) {
        Calendar calendar = new GregorianCalendar();
        System.out.println(calendar.getTime());
        System.out.println(calendar.getTimeZone());
        System.out.println(calendar.getFirstDayOfWeek());
        System.out.println(calendar.getWeekYear());
    }
}

Math

數學經常使用類

public class Demo4 {
    public static void main(String[] args) {
        System.out.println(Math.max(10,20));
        System.out.println(Math.abs(-1));
        System.out.println(Math.ceil(1.1));
        System.out.println(Math.PI);
        System.out.println(Math.E);
    }
}

Random

import java.util.Random;

public class Demo5 {
    public static void main(String[] args) {
        System.out.println(new Random().nextInt(10));
        System.out.println(new Random().nextDouble());
    }
}

Enum(枚舉類)

枚舉類也是一個類,能夠定義屬性和方法,甚至能夠寫構造方法,填寫具體的枚舉類對象的時候,能夠帶參數,可是要跟構造方法進行匹配

初級用法
public class Demo6 {
    public static void main(String[] args) {
        System.out.println(Gender.FEMALE);
    }
}
public enum Gender {
    MALE,FEMALE;
}
高階用法

每一個枚舉的子枚舉均可以看做是枚舉的子類,能夠定義相關方法以及相應的set/get方法來獲取子枚舉攜帶的一些信息

public enum WEEK_DAY {
    MONDAY(0),
    TUESDAY(1),
    WEDNESDAY(2),
    THURSDAY(3),
    FRIDAY(4),
    SATURDAY(5),
    SUNDAY(6);

    private int value;
    public void method(int i){
        System.out.println(i);
    }

    public int getValue(){
        return this.value;
    }



    WEEK_DAY(int i) {
        this.value = i;
    }
}

public class Demo6 {
    public static void main(String[] args) {
        System.out.println(WEEK_DAY.FRIDAY.getValue());
    }
}

集合

定義

一個用來儲存數據的容器

數組

形如:int[],String[]的數據結構

特色:

  1. 數據的類型必須是一致的
  2. 數組必須在聲明的時候顯示的給出長度
  3. 數組在插入和刪除的時候,頻繁的移動元素,效率比較低
  4. 數組在查找元素的時候能夠按照下標查找

Collection

具備的基本操做:

  1. 添加,存儲的是對象的引用
    1. add
  2. 容器中元素的個數
    1. size
  3. 刪除
    1. remove
    2. clear
    3. removeAll
    4. retainAll
  4. 判斷元素是否存在集合中
    1. contains
    2. isEmpty
  5. 遍歷元素
    1. iterator
List
特色

不惟一,有序

ArrayList

ArrayList實現了長度可變的數組,在內存中分配連續的空間

  • 優勢:遍歷元素和隨機訪問元素的效率比較高
  • 缺點:添加和刪除須要大量移動元素效率低,按照內容查詢效
    率低
LinkedList

LinkedList採用鏈表存儲方式

  • 優勢:插入、刪除元素時效率比較高
  • 缺點:遍歷和隨機訪問元素效率低下

LinkedList特有方法

    1. addFirst(Object obj) 添加頭
    2. addLast(Object obj) 添加尾
    3. offerFirst(Object obj) 1.6版本以後的加頭,尾巴
    4. offerLast(Object obj) 1.6版本以後的加頭,尾巴
    1. removeFirst() 刪除頭 獲取元素並刪除元素
    2. removeLast() 刪除尾
    3. pollFirst() 1.6版本以後的刪頭,刪尾
    4. pollLast() 1.6版本以後的刪頭,刪尾
    1. getFirst() 獲取頭 獲取元素但不刪除
    2. getLast() 獲取尾
    3. peekFirst() 1.6版本以後的獲取頭,獲取尾
    4. peekLast() 1.6版本以後的獲取頭,獲取尾
List接口特有方法
    1. add(index,element) 在指定索引的位置上插入元素
    2. addAll(index,Collection) 在指定的引的位置上插入整個集合的元素
    3. addAll(Collection) 在結束插入整個集合的元素
    1. remove(index)
    1. set(index,element)
    2. 使用element替換指定索引位置上的元素
  1. 查(獲取元素)
    1. get(index)
    2. subList(from,to)
    3. listIterator();
Set
特色:惟一,無序
HashSet
  • 採用Hashtable哈希表存儲結構

  • 優勢:添加速度快,查詢速度快,刪除速度快

  • 缺點:無序

  • LinkedHashSet

    • 採用哈希表存儲結構,同時使用鏈表維護次序
    • 有序(添加順序)
Hash表原理

  • 代碼驗證HashSet的無序性不惟一性
  • 使用HashSet存儲自定義對象,重寫hashCode方法與equals方法

  • 關鍵代碼

    HashSet hs=new HashSet();//建立HashSet對象
    hs.add(new Person("張三",20));
    hs.add(new Person("李四",22));
    hs.add(new Person("王五",23));
    hs.add(new Person("李四",22));
    • HashSet存儲進了相同的對象,不符合實際狀況
    • 解決方案: 重寫equals方法與hashCode方法
    • HashSet的操做
    @Override
    public int hashCode() {
    System.out.println(this.name+".....hashCode");
    return 60;
    }
    • hashCode都相同,不符合實際狀況,繼續升級

      • 修改hashCode方法

        @Override
        public int hashCode() {
        System.out.println(this.name+".....hashCode");
        return this.name.hashCode()+age;
        }
  • 總結:

    • HashSet是經過元素的兩個方法,hashCode和equals方法來保證元素的惟一性的 。若是元素的HashCode值相同,纔會判斷equals是否爲true ,若是元素的hashCode值不一樣,不會調用equals方法
TreeSet
  • 採用二叉樹(紅黑樹)的存儲結構
  • 優勢:有序(排序後的升序)查詢速度比List快
  • 缺點:查詢速度沒有HashSet快
Comparable 接口

全部能夠「排序」的類都實現了java.lang.Comparable 接口 compareTo(Object obj) 方法。

該方法:

返回 0 表示 this == obj
返回正數 表示 this > obj
返回負數 表示 this < obj

實現了Comparable 接口的類經過實現 comparaTo 方法從而肯定該類對象的排序方式。

public class StrLenComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (o1.length()>o2.length()) {
return 1;
}
if (o1.length()<o2.length()) {
return -1;
}
return o1.compareTo(o2);//長度相同, 按字母
}
}
public static void sortDemo(){
List<String> list=new ArrayList<String>();
..添加元素
sop(list);
Collections.sort(list);//按字母排序
sop(list);
//按照字符串長度排序
Collections.sort(list,new StrLenComparator());
sop(list);
}
Iterator接口

全部實現了Collection接口的容器類都有一個iterator方法用以返回一個實現了Iterator接口的對象。

Iterator對象稱做迭代器,用以方便的實現對容器內元素的遍歷操做。

Iterator接口定義了以下方法:

boolean hasNext(); //判斷是否有元素沒有被遍歷
Object next(); //返回遊標當前位置的元素並將遊標移動到下一個位置
void remove(); //刪除遊標左面的元素,在執行完next以後該
//操做只能執行一次

全部的集合類均未提供相應的遍歷方法,而是把遍歷交給迭代器完成。迭代器爲集合而生,與門實現集合遍歷

Iterator是迭代器設計模式的具體實現

Iterator方法:

  • boolean hasNext():判斷是否存在另外一個可訪問的元素
  • Object next():返回要訪問的下一個元素
  • void remove():刪除上次訪問返回的對象

可使用Iterator遍歷的本質 :實現Iterable接口

ListIterator

在迭代過程當中,準備添加或者刪除元素

ArrayList al=new ArrayList();
al.add("java1");//添加元素
al.add("java2");
al.add("java3");
//遍歷
Iterator it=al.iterator();
while(it.hasNext()){
Object obj=it.next();
if (obj.equals("java2")) {
al.add("java9");
}
sop("obj="+obj);
}
ListIterator的做用:解決併發操做異常

在迭代時,不可能經過集合對象的方法(al.add(?))操做集合中的元素,會發生併發修改異常。 因此,在迭代時只能經過迭代器的方法操做元素,可是Iterator的方法是有限的,只能進行判斷(hasNext),取出(next),刪除(remove)的操做,若是想要在迭代的過程當中進行向集合中添加,修改元素等就須要使用 ListIterator接口中的方法

ListIterator li=al.listIterator();
while(li.hasNext()){
Object obj=li.next();
if ("java2".equals(obj)) {
li.add("java9994");
li.set("java002");
}
}

Map

接口存儲一組鍵值對象,提供key到value的映射

Map相關方法
  1. 添加
    1. put(key,value) 添加元素
  2. 刪除
    1. clear() 清除全部
    2. remove(key) 根據key去移除
  3. 判斷
    1. containsKey(key)是否包含指定的key
    2. containsValue(value) 是否包含指定的值
    3. isEmpty() 判斷集合中元素是否爲 空
  4. 遍歷
    1. get(key)
    2. size()
    3. values()
    4. entrySet()
    5. keySet()

Collections工具類

Collections和Collection不一樣,前者是集合的操做類,後者是集合接口

Collections提供的靜態方法 :

  1. addAll():批量添加
  2. sort():排序
  3. binarySearch():二分查找
  4. fill():替換
  5. shuffle():隨機排序
  6. reverse():逆序

集合總結


集合和數組的比較

數組不是面向對象的,存在明顯的缺陷,集合彌補了數組的一些缺點,比數組更靈活更實用,可大大提升軟件的開發效率,並且不一樣的集合框架類可適用不一樣場合。具體以下:

  1. 數組能存放基本數據類型和對象,而集合類中只能存放對象
  2. 數組容易固定沒法動態改變,集合類容量動態改變
  3. 數組沒法判斷其中實際存有多少元素, length只告訴了數組的容量,而集合的size()能夠確切知道元素的個數
  4. 集合有多種實現方式和不一樣適用場合,不像數組僅採用順序表方式
  5. 集合以類的形式存在,具備封裝、繼承、多態等類的特性,經過簡單的方法和屬性便可實現各類複雜操做,大大提升了軟件的開發效率

Collection和Collections的區別

  1. Collection是Java提供的集合接口,存儲一組不惟 一,無序的對象。它有兩個子接口List和Set。
  2. Java還有一個Collections類,專門用來操做集合類,它提供了一系列的靜態方法實現對各類集合的搜索、排序、線程安全化等操做。

ArrayList和LinkedList的聯繫和區別

  1. ArrayList實現了長度可變的數組,在內存中分配連續空間。遍歷元素和隨機訪問元素效率比較高
  2. LinkedList採用鏈表存儲方式。插入、刪除元素效率比較高

Vector和ArrayList的聯繫和區別

  1. 實現原理相同,功能相同,都是長度可變的數組結構,不少時候能夠互用
  2. 二者的主要區別以下
    1. Vector是早期的JDK接口, ArrayList是替代Vector的新接口
    2. Vector線程安全, ArrayList重速度輕安全,線程非安全
    3. 長度須要增加時, Vector默認增加一倍, ArrayList增加50%(1.5+1)

HashMap和Hashtable的聯繫和區別

  1. 實現原理相同,功能相同,底層都是哈希表結構,查詢速度快,在不少狀況下能夠互用

  2. 二者的主要區別以下 :

    1. Hashtable是早期的JDK提供的接口, HashMap是新版的JDK提供的接口
    2. Hashtable繼承Dictionary類, HashMap實現Map接口
    3. Hashtable是線程安全, HashMap線程非安全
    4. Hashtable不容許null值, HashMap容許null值

IO

流的基本概念

流是指一連串流動的字符,是以先進先出方式發送信息的通道 。

  1. XXX->程序-->輸入流

  2. 程序->XXX-->輸出流

Java流的分類

輸入輸出流是相對於計算機內存來講的,而不是相對於源和目標

字節流是 8 位通用字節流,字符流是 16 位 Unicode 字符流

  1. 功能不一樣

    1. 節點流:能夠直接從數據源或目的地讀寫數據

    2. 處理流(包裝流):不直接鏈接到數據源或目的地,是其餘流進行封裝。目的主要是簡化操做和提升性能

    3. 節點流和處理流的關係

      1. 節點流處於io操做的第一線,全部操做必須經過他們進行

      2. 處理流能夠對其餘流進行處理(提升效率或操做靈活性)

文件的讀寫

  1. 用FileInputStream和FileOutputStream讀寫文本文件

    1. 使用FileInputStream 讀文本文件

      1. 引入相關的類

      2. 構造文件輸入流FileInputStream對象

      3. 讀取文本文件的數據

      4. 關閉文件流對象

        import java.io.FileInputStream;
        import java.io.FileNotFoundException;
        import java.io.IOException;
        
        public class Demo {
            public static void main(String[] args) {
                FileInputStream fileInputStream;
                byte[] bytes = new byte[1024];
                try {
                    fileInputStream= new FileInputStream("test.txt");
                    fileInputStream.read(bytes);
                    System.out.println(new String(bytes));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                fileInputStream.close();
            }
        }
    2. 使用FileOutputStream 寫文本文件

      1. 引入相關的類

      2. 構造文件數據 流輸出對象

      3. 將數據寫入文 本文件

      4. 關閉文件流對象

        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.nio.charset.StandardCharsets;
        
        public class Demo2 {
            public static void main(String[] args) throws IOException {
                FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
                String string = "aaaaa";
                fileOutputStream.write(string.getBytes(StandardCharsets.UTF_8));
                fileOutputStream.close();
            }
        }
  2. 用BufferedReader和BufferedWriter讀寫文本文件

    1. 使用 BufferedReader 讀文本文件

      import java.io.*;
      
      public class Demo3 {
          public static void main(String[] args) throws IOException {
              FileReader fileReader = new FileReader("test.txt");
              BufferedReader bufferedReader = new BufferedReader(fileReader);
              String result = "";
              while ((result = bufferedReader.readLine())!=null){
                  System.out.println(result);
              }
              bufferedReader.close();
              fileReader.close();
          }
      }
    2. 使用 BufferedWriter 寫文件

      import java.io.BufferedWriter;
      import java.io.FileWriter;
      import java.io.IOException;
      
      public class Demo4 {
          public static void main(String[] args) throws IOException {
              FileWriter fileWriter = new FileWriter("test.txt");
              BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
              String string = "aaaaaaaa\naaaaaa\taaaa\nsdsdsds";
              bufferedWriter.write(string);
              bufferedWriter.close();
              fileWriter.close();
          }
      }

二進制文件的讀寫

使用DataInputStream和DataOutputStream讀寫二進制文件以及基本數據類型數據的讀寫

  1. 寫入數據

    DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
    dos.writeInt(234);
    dos.writeBoolean(false);
    dos.writeDouble(9943.00);
    dos.writeUTF("中國");
    dos.close();
  2. 讀取數據

    DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
    int num=dis.readInt();
    boolean isFind=dis.readBoolean();
    double price=dis.readDouble();
    String str=dis.readUTF();
    System.out.println(num+"\t"+isFind+"\t"+price+"\t"+str);

對象的讀寫

使用ObjectInputStream和ObjectOutputStream讀寫對象(序列化與反序列化)

注意:傳輸的對象須要實現Serializable接口

  1. 序列化

    ObjectOutputStream oos=new ObjectOutputStream(new
    FileOutputStream("obj.txt"));
    oos.writeObject(new Person("張三",19));
    oos.close();
  2. 反序列化

    ObjectInputStream ois=new ObjectInputStream(new
    FileInputStream("obj.txt"));
    Person p=(Person)ois.readObject();
    System.out.println(p);
  3. 注意:

    1. 類必須實現Serializable接口
    2. 給類加個序列化編號,給類定義一個標記,新的修改後的類還能夠操做曾經序列化的對象
    3. 靜態是不能被序列化的,序列化只能對堆中的進行序列化 ,不能對「方法區」中的進行序列化
    4. 不須要序列化的字段前加 transient

總結

  1. 文件操做:FileReader, FileWriter
  2. 字符操做:FileInputStream, FileOutputStream
  3. 基本數據類型操做:DataInputStream, DataOutputStream
  4. 操做對象:ObjectInputStream ,ObjectOutputStream

線程

核心概念

  1. 程序:Program,是一個指令的集合
  2. 進程:Process,(正在執行中的程序)是一個靜態的概念
    1. 進程:Process,(正在執行中的程序)是一個靜態的概念
    2. 每一個進程都是獨立的,由3部分組成cpu,data,code
    3. 缺點:內存的浪費, cpu的負擔
  3. 線程:是進程中一個「單一的連續控制流程」
    1. 線程又被稱爲輕量級進程(lightweight process)
    2. 一個進程可擁有多個並行的(concurrent)線程
    3. 一個進程中的線程共享相同的內存單元/內存地址空間->能夠訪問相同的變量和對象,並且它們從同一堆中分配對象->通訊、數據交換、同步操做
    4. 因爲線程間的通訊是在同一地址空間上進行的,因此不須要額外的通訊機制,這就使得通訊更簡便並且信息傳遞的速度也更快

多線程的實現

  1. 在Java中負責線程的這個功能的是Java.lang.Thread 這個類

  2. 能夠經過建立 Thread 的實例來建立新的線程

  3. 每一個線程都是經過某個特定Thread對象所對應的方法run( )來完成其操做的,方法run( )稱爲線程體

  4. 經過調用Thead類的start()方法來啓動一個線程

  5. 具體實現:

    1. 繼承Thread類
    2. 重寫run方法
    3. 建立對象,調用start()方法啓動線程
    public class ThreadDemo01 extends Thread {
    //重寫父爲的run方法
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    System.out.println("第"+i+"次threadrun........");
    }
    }
    public static void main(String[] args) {
    //建立對象,就建立好一個線程
    ThreadDemo01 d=new ThreadDemo01();
    //d.run();//啓動線程使用start方法
    d.start();
    for(int i=0;i<5;i++){
    System.out.println("main-->"+i);
    }
    }
    }
  6. 線程的執行

    1. xxx.run();僅僅是對象調方法,而是建立了線程但並無運行
    2. xxx.start();//開啓線程並執行該線程的run方法
  1. 操做步驟

    1. 實現Runnable接口
    2. 重寫run方法
    3. 建立對象,調用start()方法啓動線程
    public class RunableDemo implements Runnable {
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    System.out.println("第"+i+"次threadrun........");
    }
    }
    public static void main(String[] args) {
    //建立對象,就建立好一個線程
    RunableDemo rd=new RunableDemo();
    Thread t=new Thread(rd);
    t.start();
    for(int i=0;i<5;i++){
    System.out.println("main-->"+i);
    }
    } }
  1. 繼承Thread類方式的缺點:那就是若是咱們的類已經從一個類繼承(如小程序必須繼承自 Applet 類),則沒法再繼承 Thread類
  2. 經過Runnable接口實現多線程
    1. 優勢:能夠同時實現繼承。實現Runnable接口方式要通用一些
      1. 避免單繼承
      2. 方便共享資源 同一份資源 多個代理訪問

線程的狀態

  1. 新生狀態 :用new關鍵字創建一個線程後,該線程對象就處亍新生狀態 ;處亍新生狀態的線程有本身的內存空間,經過調用start()方法進入就緒狀態
  2. 就緒狀態 :處亍就緒狀態線程具有了運行條件,但還沒分配到CPU,處於線程就緒隊列,等待系統爲其分配CPU;當系統選定一個等待執行的線程後,它就會從就緒狀態進入執行狀態,該動做稱爲「CPU調度」
  3. 運行狀態 :在運行狀態的線程執行本身的run方法中代碼,直到等待某資源而阻塞或完成任何而死亡 ;若是在給定的時間片內沒有執行結束,就會被系統給換下來回到等待執行狀態
  4. 阻塞狀態 :處於運行狀態的線程在某些狀況下,如執行了sleep(睡眠)方法,或等待I/O設備等資源,將讓出CPU並暫時中止本身運行,進入阻塞狀態;在阻塞狀態的線程並能進入就緒隊列。只有當引發阻塞的緣由消除時,如睡眠時間已到,或等待的I/O設備空閒下來,線程便轉入就緒狀態,從新到就緒隊列中排隊等待,被系統選中後從原來中止的位置開始繼續執行
  5. 死亡狀態 :死亡狀態是線程生命週期中的最後一個階段。線程死亡的緣由有三個,一個是正常運行的線程完成了它的所有工做;另外一個是線程被強制性地終止,如經過stop方法來終止一個線程【不推薦使用】 ;三是線程拋出未捕獲的異常

線程操做的相關方法

阻塞狀態(sleep/yield/join方法)

有三種方法能夠暫停Thread執行:

  1. sleep:
    不會釋放鎖, Sleep時別的線程也不能夠訪問鎖定對象。
  2. yield:
    讓出CPU的使用權,從運行態直接進入就緒態。讓CPU從新挑選哪個線程進入運行狀態。
  3. join:
    當某個線程等待另外一個線程執行結束後,才繼續執行時,使調用該方法的線程在此以前執行完畢,也就是等待調用該方法的線程執行完畢後再往下繼續執行

多線程的安全性問題

public class TicketImplements implements Runnable {
private int tick=5;
public void run() {
while(true){
if (tick>0) {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+"賣票:"+tick--);
}
}
}
public static void main(String[] args) {
TicketImplements ti=new TicketImplements();
new Thread(ti).start();
new Thread(ti).start();
new Thread(ti).start();
new Thread(ti).start();
}

線程的同步不死鎖

多線程的運行出現了安全問題

使用同步解決多線程的安全性問題

  1. 同步代碼塊

    public void run() {
    while(true){
    synchronized (this) {//一般將當前對象做爲同步對象
    if (tick>0) {
    Thread.sleep(10);
    System.out.println(Thread.currentThread().getName()+"賣
    票:"+tick--);
    }
    }
    }
    }
    1. 同步的前提

      1. 必須有兩個或兩個以上的線程
      2. 必須是多個線程使用同一資源
      3. 必須保證同步中只能有一個線程在運行
    2. 將須要同步的代碼放到方法中

      public void run() {
      while(true){
      sale();
      }
      }
      public synchronized void sale(){
      //一般將當前對象做爲同步對象
      if (tick>0) {
      Thread.sleep(10);
      System.out.println(Thread.currentThread().getName()+"賣票:"+tick--);
      }
      }
    3. 同步監視器

      1. synchronized(obj){}中的obj稱爲同步監視器
      2. 同步代碼塊中同步監視器能夠是任何對象,可是推薦使用共享資源做爲同步監視器
      3. 同步方法中無需指定同步監視器,由於同步方法的監視器是this,也就是該對象自己
    4. 同步監視器的執行過程

      1. 第一個線程訪問,鎖定同步監視器,執行其中代碼
      2. 第二個線程訪問,發現同步監視器被鎖定,沒法訪問
      3. 第一個線程訪問完畢,解鎖同步監視器
      4. 第二個線程訪問,發現同步監視器未鎖,鎖定並訪問

死鎖

  1. 同步能夠保證資源共享操做的正確性,可是過多同步也會產生死
  2. 死鎖通常狀況下表示互相等待,是程序運行時出現的一種問題

線程通訊

Java提供了3個方法解決線程之間的通訊問題

網絡編程

網絡的概念

一組相互鏈接的計算機

網絡編程的三要素

  1. IP地址:惟一標識網絡上的每一臺計算機,兩臺計算機之間通訊的必備要素
  2. 端口號:計算機中應用的標號(表明一個應用程序)0-1024系統使用或保留端口 ,有效端口0-65536
  3. 通訊協議:通訊的規則TCP,UDP

網絡模型

OSI參考模式:開放系統互連參考模型(Open System Interconnect)

TCP/IP參考模型:傳輸控制/網際協議 Transfer Controln Protocol/Internet Protocol

IP地址的表示方法

  1. IP 地址: 32位, 由4個8位二進制數組成
  2. IP表示方法:點分十進制
  3. 舉例
    1. 二進制:11000000.10101000.00000001.11001000
    2. 十進制:192.168.1.200
  4. IP地址 = 網絡ID +主機ID
    1. 網絡ID:標識計算機或網絡設備所在的網段
    2. 主機ID:標識特定主機或網絡設備

**IP地址所對應的對象->InetAddress **

得到百度主機名:

InetAddress ia2=InetAddress.getByName("www.baidu.com");
System.out.println("其它主機名稱:"+ia2.getHostAddress());

端口

  1. 端口:port
    端口是虛擬的概念,並非說在主機上真的有若干個端口。經過
    端口,能夠在一個主機上運行多個網絡應用程序。

傳輸協議

  1. UDP:至關於収短信(有字數限制),
    不須要創建鏈接,
    數據報的大小限制在64k內,
    效率較高,不安全,容易丟包
  2. TCP:至關於打電話,須要創建鏈接,
    效率相對比較低,數據傳輸安全,
    三次握手完成。
    (點名->答到->確認)

Socket套接字

  1. 網絡上的兩個程序經過一個雙向的通訊鏈接實現數據的交換, 這個鏈接的一端稱爲一個socket。
  2. Java中使用Socket完成TCP程序的開収,使用此類能夠方便的創建可靠的、 雙向的、 持續性的、 點對點的通信鏈接
  3. 在Socket的程序開發中,服務器端使用ServerSocket等待客戶端的鏈接,對於java的網絡程序來說,每個客戶端都使用一個Socket對象表示

基於TCP協議的Socket編程

進行網絡通訊時, Socket須要藉助數據流來完成數據的傳遞工做

  1. 客戶端

    1. 創建鏈接
    Socket socket=new Socket("localhost",8800);
    1. 打開Socket關聯的輸入輸出流
    OutputStream os=socket.getOutputStream();
    1. 數據流中讀寫信息
    String info="用戶名: Tom;用戶密碼: 123456";
    os.write(info.getBytes());
    socket.shutdownOutput();
    1. 關閉全部的數據流和Socket

      os.close();
      socket.close();
  2. 服務端

    1. 創建鏈接,處理髮送到指定端口的數據

      ServerSocket server=new ServerSocket(8800);
    2. 獲取客戶端對象

      Socket socket=server.accept();
    3. 數據流中讀寫信息

      InputStream is=socket.getInputStream();
      byte[] buf=new byte[1024];
      int len=is.read(buf);
      syso(new String(buf,0,len))
      socket.shutdownInput();
    4. 關閉全部的數據流和Socket

      is.close();
      socket.close();
      server.close()

Socket中實現對象的傳遞

序列化對象

User user=new User();//User是用戶類
user.setLoginName("Tom");
user.setPwd("123456");
oos.writeObject(user);

基於UDP的網絡編程

通訊雙發不須要創建鏈接 ,通訊雙方徹底平等

import java.io.IOException;
import java.net.*;


public class Client {
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramSocket datagramSocket = new DatagramSocket(new InetSocketAddress(InetAddress.getByName("localhost"),8888));
        datagramSocket.connect(InetAddress.getByName("localhost"), 9999);
        ReadThread readThread = new ReadThread(datagramSocket);
        WriteThread writeThread = new WriteThread(datagramSocket);
        readThread.start();
        writeThread.start();
    }
}

public class Client2 {
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramSocket datagramSocket = new DatagramSocket(new InetSocketAddress(InetAddress.getByName("localhost"),9999));
        datagramSocket.connect(InetAddress.getByName("localhost"), 8888);
        ReadThread readThread = new ReadThread(datagramSocket);
        WriteThread writeThread = new WriteThread(datagramSocket);
        readThread.start();
        writeThread.start();
    }
}

import java.nio.charset.StandardCharsets;

public class ReadThread extends Thread{
    private DatagramSocket datagramSocket;
    private byte[] bytes = new byte[1024];
    private byte[] bytes1;
    DatagramPacket datagramPacket = new DatagramPacket(this.bytes, 0,1024);

    public ReadThread(DatagramSocket datagramSocket){
        this.datagramSocket = datagramSocket;
    }
    @Override
    public void run() {
        super.run();
        while (true){
            try {
                this.datagramSocket.receive(this.datagramPacket);
                this.bytes1 = new String(this.bytes, 0, this.bytes.length).getBytes(StandardCharsets.UTF_8);
                System.out.println(new String(this.bytes1, 0, this.bytes1.length));
                Thread.sleep(2);
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

import java.util.Scanner;

public class WriteThread extends Thread{
    private DatagramSocket datagramSocket;
    private String message = "";
    private byte[] bytes = new byte[1024];
    private Scanner scanner = new Scanner(System.in);

    public WriteThread(DatagramSocket datagramSocket){
        this.datagramSocket = datagramSocket;
    }

    @Override
    public void run() {
        super.run();
        while (true){
            synchronized (WriteThread.class){
                System.out.print("輸入:");
                this.message = this.scanner.nextLine();
            }
            DatagramPacket datagramPacket = null;
            try {
                datagramPacket = new DatagramPacket(message.getBytes(StandardCharsets.UTF_8),0, message.length(), new InetSocketAddress(InetAddress.getByName("localhost"),datagramSocket.getPort()));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            try {
                datagramSocket.send(datagramPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Lambda表達式

Lambda表達式的介紹

Lambda表達式是 Java8 中最重要的新功能之一。使用 Lambda 表達式能夠替代只有一個抽象函數的接口實現,告別匿名內部類,代碼看起來更簡潔易懂。 Lambda表達式同時還提高了對集合、框架的迭代、遍歷、過濾數據的操做

Lambda表達式的特色

  1. 函數式編程
  2. 參數類型自動推斷
  3. 代碼量少,簡潔

Lambda表達式案例

Lambda表達式應用場景

任何有函數式接口的地方

函數接口

只有一個抽象方法(Object類中的方法除外) 的接口是函數式接口

  1. Supplier 表明一個輸出
  2. Consumer 表明一個輸入
  3. BiConsumer 表明兩個輸入
  4. Function 表明一個輸入,一個輸出(通常輸入和輸出是不一樣類型的)
  5. UnaryOperator 表明一個輸入,一個輸出(輸入和輸出是相同類型的)
  6. BiFunction 表明兩個輸入,一個輸出(通常輸入和輸出是不一樣類型的)
  7. BinaryOperator 表明兩個輸入,一個輸出(輸入和輸出是相同類型的)

方法的引用

方法引用是用來直接訪問類或者實例的已經存在的方法或者構造方法,方法引用提供了一種引用而不執行方法的方式,若是抽象方法的實現剛好可使用調用另一個方法來實現,就有可能可使用方法引用

方法引用的分類

  1. 靜態方法引用:若是函數式接口的實現剛好能夠經過調用一個靜態方法來實現,那麼就可使用靜態方法引用
  2. 實例方法引用:若是函數式接口的實現剛好能夠經過調用一個實例的實例方法來實現,那麼就可使用實例方法引用
  3. 對象方法引用:抽象方法的第一個參數類型恰好是實例方法的類型,抽象方法剩餘的參數剛好能夠當作實例方法的參數。若是函數式接口的實現能由上面說的實例方法調用來實現的話,那麼就可使用對象方法引用
  4. 構造方法引用:若是函數式接口的實現剛好能夠經過調用一個類的構造方法來實現,那麼就可使用構造方法引用
相關文章
相關標籤/搜索