主頁 > 後端開發 > 爆肝!!!!JavaSE知識點1.3w字總結

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

2021-02-22 13:02:17 後端開發

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

Java基礎語法知識

關鍵名詞

jdk

jdk(java development kit),即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. 構造方法參考:如果函式式介面的實作恰好可以通過呼叫一個類的構造方法來實作,那么就可以使用構造方法參考

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/262197.html

標籤:java

上一篇:【Spring】DI:回圈依賴 singleton 三層快取

下一篇:PyQt5入門(二十八)用PyInstaller打包PyQt5應用 & 使用PyQtGraph進行資料可視化

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more