測試人員學Java入門指南

測試開發剛哥發表於2022-02-11

目標讀者

本指南特別適合有Python基礎的同學學習Java入門,對於沒有任何程式設計經驗的同學可能會存在困難。

為什麼測試人員要學Java

選擇Java,應該不錯。TesterHome測試論壇知名大佬基本都是以Java技術棧為主,少部分是Golang和Python。我公司2021年校招的兩個同濟大學研究生,測試開發,也是以Java為主。有一個測開同事跳槽去了美團,拿了高薪,只會Java。有一個測開同事跳槽去了創業公司做了測試架構師,只會Java。招聘網站搜尋測試開發20K以上職位,基本都要求會Java。我接觸到的開發,Java程式設計師佔80%以上。

測試人員用Java能幹嘛

如果你的公司是以Java技術棧為主,那麼你可以用Java做所有事情,而且有些事情只能用Java來做。這個問題挺關鍵的,學習一門語言肯定是要能夠學以致用。在自動化測試,Java會顯得稍微有點笨重,而Python會適合一點。你可以用Python來寫介面自動化指令碼,在小範圍內使用,但是當團隊變大以後,指令碼如何規範如何維護,就成了一個很大的問題,而Java由於靜態語言特性和麵向物件程式設計,正好可以用來解決這個問題。在測試平臺和效能測試,Java有很成熟的Web開發框架和配套的生態。在測試工具開發,公司封裝好的Java庫可以拿來即用,碰到問題也可以找開發幫忙。白盒測試,基本上都是要靠Java來做的,看程式碼,用JaCoCo統計程式碼覆蓋率。其他專項比如流量錄製回放、全鏈路壓測、Dubbo介面測試,都只能使用Java來做。

測試人員怎麼學Java

我推薦刷完一遍基礎語法後,在LeetCode上面刷演算法題來加強練習。Java還是有一定的學習門檻的,初學者可能學起來會有些吃力,可以先從Python入手,瞭解程式語言的底層邏輯,等對程式設計有些許感知以後,再學習Java。基礎語法可以快速瀏覽一遍,一遍並不會就能記住了,需要在編碼中持續加強記憶。光學語法也不行,學習Java和其他程式語言一樣,需要多敲多練,刷演算法題,既能熟悉Java語法,也能熟悉演算法,一舉兩得,題做不來就先把答案背一遍再做。另外,可以在工作中主動找研發開通下程式碼許可權,嘗試Review開發程式碼,看多了,有些技巧也會知道了。有機會,可以用Java寫點工具或者平臺,實踐出真知。

搭建環境

安裝Java

Java的安裝包是個.exe檔案,特殊地方在於檔名不是java-xxx.exe而是jdk-xxx.exe,比如jdk-8u281-windows-x64.exejdkJava Development Kit 的縮寫,指Java開發工具包,包括以下內容:

JDK的最新版本為15,但是國內大多數公司仍然使用的是JDK8,這是因為JDK8是各方面都很成熟穩定的版本,並且基於JDK8開發的業務系統已經具有一定規模,新版本JDK並不能完全無感知的遷移,需要做程式碼修改和測試,會是一筆巨大開銷,為了降低成本和規避相容問題風險,JDK8沿用到了至今。JDK8的下載地址如下:

https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

選擇相應的版本下載:

比如我的電腦是Windows 64位的系統,就選擇了Windows x64這個版本,會下載到一個jdk-8u281-windows-x64.exe檔案。Java已經被Oracle收購了,需要登入Oracle賬號後才能下載,沒有賬號註冊一個也很方便:

下載後可以開始安裝了:

安裝到預設位置即可,直接下一步。中途會讓選擇JRE(Java Runtime Environment,Java執行環境)的目標資料夾:

依然保持預設即可。安裝結束後就能看到兩個新資料夾了:

以前,還需要配置系統環境變數,設定JAVA_HOMECLASSPATH才能使用Java(具體方法百度有很多)。現在,安裝完成即可用,省去了不少麻煩,速度加快。開啟cmd輸入java -version,命令能執行成功就表示Java已經安裝好了:

安裝IntelliJ IDEA

JetBrains全家桶中也有專門用來寫Java的,叫做IntelliJ IDEA,一般只說後面一個單詞“哎迪兒”就知道是這個東西了。下載地址為:

https://www.jetbrains.com/idea/download/#section=windows

個人建議選擇旗艦版,看著齊全。下載後雙擊ideaIU-2020.3.2.exe安裝,先別忙著開啟。

Maven倉庫

Maven是用來管理Java第三方包的主流倉庫工具,通過pom.xml檔案來配置安裝即可,在mvnrepository網站上能檢索到所需配置資訊:

https://mvnrepository.com/

官方倉庫有時候下載速度很慢,本文用國內映象替代,提高首次開啟時同步倉庫速度。我們先把Maven中央倉庫從Apache替換成阿里雲。開啟本地目錄D:\Program Files\JetBrains\IntelliJ IDEA 2020.3.2\plugins\maven\lib\maven3\conf

編輯settings.xml檔案,找到<mirrors>標籤,新增程式碼:

    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>*</mirrorOf>
      <name>阿里雲公共倉庫</name>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>

這是新版寫法,官網https://maven.aliyun.com/mvn/guide有說明。

接著可以開啟IDEA了,歡迎介面映入眼簾:

新建專案

選擇新建Maven專案:

填寫專案名和存放位置:

pom.xml檔案中新增倉庫配置:

    <repositories>
        <repository>
            <id>public</id>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <url>https://maven.aliyun.com/repository/public</url>
        </pluginRepository>
    </pluginRepositories>

記得點選右上角的Load Maven Changes按鈕,此時前面切換倉庫的作用就體現出來了,右下角同步速度比預設明顯增快。至此,以阿里云為Maven中央倉庫的專案就建立好了。

其他設定

UTF-8

網路自動代理

基礎語法

Java雖然學習門檻有點高,但是如果熟悉Python以後,再看Java基礎語法,其實是非常簡單的。

4個概念

  • 物件:Java是純物件導向程式語言,物件的概念有點抽象,具體來說可以是一條狗,也可以是某個人。
  • 類:類是物件的模板,有點像克隆的母體。
  • 屬性:屬性就是狀態,相當於變數。
  • 方法:方法就是行為,跟函式類似,完成某個特定功能。

Hello World

Java的Hello World經常拿來和其他語言比較,嫌它囉嗦,然而囉嗦的背後是嚴謹:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Java把每個語法都顯式的表達了出來,閱讀程式碼就能知道是什麼意思,不會產生額外的意想不到的結果。

基本語法

  • public static void main(String[] args),是所有Java程式的執行入口。
  • 原始檔字尾是.java,原始檔名稱必須和類名一致。
  • 原始檔編譯後的檔案字尾是.class
  • Java是大小寫敏感的,類名首字母應該大寫,方法名首字母小寫,也就是駝峰命名法。

識別符號

類名、屬性名和方法名都被稱為識別符號,Java識別符號規則如下:

  • 識別符號是大小寫敏感的
  • 所有的識別符號都應該以字母(A-Z或者a-z)、美元符($)、或者下劃線(_)開始
  • 首字元之後可以是字母(A-Z或者a-z),美元符($)、下劃線(_)或數字的任何字元組合
  • 關鍵字不能用作識別符號

比如合法的識別符號:

age、$salary、_value、__1_value

非法的識別符號:

123abc、-salary

修飾符

  • 訪問控制修飾符 : default, public, protected, private
  • 非訪問控制修飾符 : final, abstract, static, synchronized

Java的修飾符極大的提高了程式碼可閱讀性。

變數

因為Java的程式碼都必須寫到類裡面,所以就只有以下三種變數:

  • 類變數(靜態變數),相當於全域性變數
  • 成員變數(非靜態變數)
  • 區域性變數

註釋

public class HelloWorld {
   /* 這是第一個Java程式
    * 它將輸出 Hello World
    * 這是一個多行註釋的示例
    */
    public static void main(String[] args){
       // 這是單行註釋的示例
       /* 這個也是單行註釋的示例 */
       System.out.println("Hello World"); 
    }
}

八種基本型別

boolean 布林型 1個位元組 8bit(8位)

byte 位元組型別 1個位元組

char 字元型別 2個位元組

short 短整型 2個位元組

int 整型 4個位元組

long 長整型 8個位元組

double 雙精度型別 8個位元組

float 浮點型(單精度)4個位元組

預設的整數型別是int,如果要定義為long ,則要在數值後加上L或者l

預設的浮點型是double,如果要定義float,則要在數值後面加上F或者f

物件和類

我們都知道Java是純物件導向程式語言,這個物件是什麼,類是什麼,它們的關係是怎樣呢?

類和物件的關係

先看一張圖:

是girl和boy,物件是每個具體的女孩(Lucy、Rose)和男孩(David、Jack)。

這完美解釋了類和物件的關係,即:類是物件的模板

狀態和行為

物件有兩個特徵,一個是狀態(又叫做屬性),一個是行為(又叫做方法),我們拿狗來舉例,狗的狀態有品種、大小、顏色、年齡;行為有吃、跑、睡覺。如圖所示:

圖的左邊是3個狗物件,右邊是1個狗。類定義了物件應該有哪些屬性和方法,物件根據類定義好的模板,建立了個性化的例項。

程式碼實現如下:

public class Dog {
    // 屬性
    String breed;
    int size;
    String colour;
    int age;
 
    // 方法
    void eat() {
    }
 
    void run() {
    }
 
    void sleep(){
    }
}

構造方法

在通過類建立物件時,構造方法提供瞭如何建立物件的細節。Java會給類一個預設的構造方法,你也可以自定義一個或多個構造方法,構造方法命名必須和類名相同,比如:

public class Dog{
    public Dog(String breed){
    }
}

程式碼中定義了2個構造方法,根據引數不同,在構造時會呼叫相應的構造方法。

建立物件

如果沒有物件,那麼就new一個。Java是通過new關鍵字來建立物件的。比如使用預設構造方法建立物件:

Dog myDog = new Dog();

或者使用自定義構造方法建立物件:

Dog myDog = new Dog("Bulldog");

訪問物件屬性和方法

Java和大多數語言一樣,採用.運算子訪問物件屬性和方法,比如:

public class Dog {
    int age;

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    public static void main(String[] args) {
        // 建立物件
        Dog myDog = new Dog();
        // 通過方法來設定age
        myDog.setAge(2);
        // 呼叫另一個方法獲取age
        System.out.println(myDog.getAge());
        // 也可以像下面這樣訪問成員變數
        System.out.println(myDog.age);
    }
}

類存放規則

Java原始檔是用類來組織的,存放在原始檔中的類遵循下面幾項規則:

  • 一個原始檔只能有一個public類,可以有多個非public類。
  • 原始檔名必須與public類名一致。
  • package語句在首行,其次是import語句,最後是類。

八大基本資料型別

Java內建了8個基本資料型別,它們分別是byteshortintlongfloatdoublebooleanchar

每種基本資料型別都有相應的包裝類:Byte、Short、Integer、Long、Float、Double、Character。包裝類提供了物件導向的實現,比如二進位制位數(Integer.SIZE)、最小值(Integer.MIN_VALUE)、最大值(Integer.MAX_VALUE)等。

byte

8位整數,預設值是0,byte型別主要用在大型陣列中節約空間,因為它佔用的空間只有int型別的四分之一。

short

16位整數,預設值是0。跟byte型別用法類似,佔用空間是int型別的二分之一。

int

32位整數,預設值是0。最常用的整數型別。

long

64位整數,預設值是0L。超出int範圍的整數需要使用long型別。

float

32位浮點數,預設值是 0.0f。float型別用來表示小數。

double

64位浮點數,預設值是0.0d浮點數的預設類似是double型別。

boolean

1位真假值(true/false),預設值是false

char

16位Unicode字元,預設值是u0000。用來儲存任何單一字元。

第九種基本資料型別void

實際上,Java還有第九種基本資料型別void,我們經常在方法返回值那裡見到它,它的包裝類是java.lang.Void

三大變數型別

Java中的一個類可以包含3種型別的變數:區域性變數、成員變數、類變數。它們的定義位置如下圖所示:

區域性變數

區域性變數是在方法、構造方法或者語句塊中定義的變數。變數宣告和初始化都是在方法中,方法結束後,變數就會自動銷燬。

成員變數

成員變數是在類中,方法體之外定義的變數。變數在建立物件的時候例項化,可以被類中方法、構造方法和特定的語句塊訪問。

類變數

類變數跟成員變數定義的位置相同,只不過必須宣告為static型別。

成員變數和類變數在使用上有個明顯的區別是:類變數可以直接通過類名.變數形式進行訪問,成員變數則不能。比如:

public class B {
    static int classVar = 1;  // 類變數
    int memberVar = 2;  // 成員變數
}

成員變數在寫程式碼時IDEA就已經報錯了。

修飾符

Java修飾符是讓Java變得囉嗦的罪魁禍首之一。其他很多語言並沒有這麼多修飾符,取而代之的是語法規則,比如Python下劃線開頭的變數是私有變數,Golang小寫字母開頭的變數是私有變數。但是,正因為Java有著明確的修飾符,所以Java程式碼看起來是最直白的表述。

修飾符概覽

Java修飾符有兩大類,它們分別如下:

訪問控制修飾符

  • default(什麼都不寫)
  • private
  • public
  • protected

非訪問控制修飾符

  • static
  • final
  • abstract
  • synchronized
  • transient
  • volatile

修飾符通常是放在一行程式碼最前面的,起到修飾作用,比如:

public class ClassName {
   // ...
}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) {
   // 方法體
}

訪問控制修飾符

訪問控制,指的是對Java類、介面、變數、方法的訪問許可權的控制。我們知道Java每個檔案是一個類(Class),每個資料夾是一個包(Package),它們彼此之間能不能相互訪問,就是通過修飾符決定的。

訪問控制修飾符一覽表,從上往下,訪問許可權越來越小:

default

什麼都不寫,不使用任何修飾符,預設為包訪問許可權,即同一個包內都是可以訪問的

Java有個很棒的設計:同一個包裡面的類不需要import就能直接使用。

示例:

String version = "1.5.1";
boolean processOrder() {
   return true;
}

private

意思就像它的名字一樣,私有的,只有當前類的內部才可以訪問。private用來保護類的隱私,如果外部類想訪問private的變數,那麼只能通過public的getter方法暴露出去。需要注意的是,private可以用到變數、方法上,但是不能用到類和介面上(這麼做沒有意義,類總是要被外部呼叫的,介面總是要被外部實現的)。

示例:

public class Logger {
   private String format;
   public String getFormat() {
      return this.format;
   }
   public void setFormat(String format) {
      this.format = format;
   }
}

public

公開的,所有都能訪問,沒有任何限制

示例:

public static void main(String[] arguments) {
   // ...
}

protected

當前類可以訪問,子類有可能可以訪問。子類有兩種情況:

  • 子類與父類在同一個包中:子類可以訪問父類的protected。
  • 子類與父類在不同的包中:子類可以訪問,非子類內部的子類例項不能訪問。

示例:

package test1;


public class Base {
    int defaultInt;
    protected int protectedInt;
}
// 不同的包
package test2;


// 子類
public class Test extends Base {
    public void test(){       
         Test t = new Test();
         //t.defaultInt = 2; 不可見
         t.protectedInt = 3;
    }
}


// 非子類
class TestNotSub{
    public void test(){
          Test t = new Test();
          //t.defaultInt = 2; 不可見
          //t.protectedInt = 3; 不可見
    }
}

需要注意的是,protected可以用到變數、方法上,但是不能用到類(內部類除外)和介面上。

非訪問控制修飾符

static

static用來修飾變數和方法。修飾的變數叫做靜態變數/類變數,修飾的方法叫做靜態方法或/類方法。

靜態的含義是,無論例項化多少個物件,靜態變數或靜態方法只有一份。作為類變數或類方法,static的用法是可以直接通過ClassName.varName訪問類變數,或直接通過ClassName.methodName()訪問類方法,無需例項化物件。

需要注意的是,靜態方法裡面不能使用類的非靜態變數。

我以Python舉例可以更好說明這一點,Python的類方法第一個入參是cls,如果想訪問非類變數,那麼入參必須是self。

final

  • final修飾變數:通常和static一起用來宣告常量,比如static final String TITLE = "Manager";
  • final修飾方法:父類的final方法可以被子類繼承,但是不能被重寫,防止該方法的內容被篡改。
  • final修飾:final類不能被繼承。

abstract

  • abstract修飾:抽象類。
  • abstract修飾方法:抽象方法。

抽象意味著它們只定義了一個形式,沒有具體內容,一定會由其他的類或方法進行具體實現。如果類中有抽象方法,那麼這個類必須要定義為抽象類,否則會編譯報錯。

synchronized

用於修飾方法,這個方法同一時間只能被一個執行緒訪問。

transient

修飾變數,用的很少,我也看不懂。

volatile

修飾變數,變數每次被執行緒訪問時,都強制從共享記憶體中重新讀取值,當變數發生變化時,會強制執行緒將變化值寫入共享記憶體。這樣兩個執行緒在任何時候都能看到變數的同一個值。

運算子

Java一共有以下幾類運算子:

  • 算術運算子
  • 關係運算子
  • 位運算子
  • 邏輯運算子
  • 賦值運算子
  • 其他運算子

總的來說,Java運算子跟其他程式語言的運算子大同小異,可以快速瀏覽一下。

算術運算子

假設整數變數A的值為10,整數變數B的值為20:

特別的是,字首自增自減法(++a --a)和字尾自增自減法(a++ a--):

字首自增自減法(++a --a):先進行自增自減,再進行表示式運算。

字尾自增自減法(a++ a--):先進行表示式運算,再進行自增自減。

示例:

public class Test {
    public static void main(String[] args) {
        int d = 25;
        // 檢視  d++ 與 ++d 的不同
        System.out.println("d++   = " +  (d++) );
        System.out.println("++d   = " +  (++d) );
    }
}

結果為:

d++   = 25
++d   = 27

關係運算子

假設整數變數A的值為10,整數變數B的值為20:

位運算子

假設整數變數A的值為60,整數變數B的值為13:

邏輯運算子

假設布林變數A為真,布林變數B為假:

需要注意的是,如果第一個運算元已經能判斷結果了,那麼就不會執行下一個運算元,比如:

public class Test {
    public static void main(String[] args) {
        boolean a = false;
        boolean b = true;
        
        boolean c = a && b;  // a已經能判斷結果為false,不再執行b
        
        boolean d = b || a;  // b已經能判斷結果為true,不再執行a
    }
}

賦值運算子

其他運算子

條件運算子

variable x = (expression) ? value if true : value if false

示例:

public class Test {
   public static void main(String[] args){
      int a , b;
      a = 10;
      // 如果 a 等於 1 成立,則設定 b 為 20,否則為 30
      b = (a == 1) ? 20 : 30;
      System.out.println( "Value of b is : " +  b );  // 30
 
      // 如果 a 等於 10 成立,則設定 b 為 20,否則為 30
      b = (a == 10) ? 20 : 30;
      System.out.println( "Value of b is : " + b );  // 20
   }
}

條件運算子也叫做三元運算子,三元場景可以多用這個運算子簡寫程式碼。

instanceof 運算子

( Object reference variable ) instanceof  (class/interface type)

用來判斷物件是否為類的例項。比如:

String name = "James";
boolean result = name instanceof String; // 由於 name 是 String 型別,所以返回真

Java運算子優先順序

在編寫程式碼的時候,多用小括號把優先計算的表示式框起來,才不容易出錯。

迴圈結構

迴圈結構

while

while( 布林表示式 ) {
  // 迴圈體
}

只要布林表示式為True,就會一直反覆執行迴圈體。

示例:

public class Test {
   public static void main(String args[]) {
      int x = 10;
      while( x < 20 ) {
         System.out.print("value of x : " + x );
         x++;
         System.out.print("\n");
      }
   }
}

do while

do {
       // 迴圈體
}while( 布林表示式 );

無論表示式是否為True,都先執行一次迴圈體,然後就跟while一樣先判斷布林表示式,如果為True再繼續執行迴圈,為False就退出迴圈。

示例:

public class Test {
   public static void main(String args[]){
      int x = 10;
 
      do{
         System.out.print("value of x : " + x );
         x++;
         System.out.print("\n");
      }while( x < 20 );
   }
}

for

for(初始化; 布林表示式; 更新) {
    // 迴圈體
}
  • 初始化:定義一個或多個迴圈控制變數,也可以為空語句。
  • 布林表示式:根據True或False決定是否繼續執行迴圈。
  • 更新:更新迴圈控制變數。

示例:

public class Test {
   public static void main(String args[]) {
 
      for(int x = 10; x < 20; x = x+1) {
         System.out.print("value of x : " + x );
         System.out.print("\n");
      }
   }
}

Java也有更方便從陣列遍歷元素的for迴圈:

for(宣告語句 : 表示式)
{
   // 迴圈體
}
  • 宣告語句:跟陣列元素型別匹配的區域性變數。
  • 表示式:陣列或返回陣列的方法。

示例:

public class Test {
   public static void main(String args[]){
      int [] numbers = {10, 20, 30, 40, 50};
 
      for(int x : numbers ){
         System.out.print( x );
         System.out.print(",");
      }
      System.out.print("\n");
      String [] names ={"James", "Larry", "Tom", "Lacy"};
      for( String name : names ) {
         System.out.print( name );
         System.out.print(",");
      }
   }
}

break

跳出整個迴圈。

示例:

public class Test {
   public static void main(String args[]) {
      int [] numbers = {10, 20, 30, 40, 50};
 
      for(int x : numbers ) {
         if( x == 30 ) {
            break;  // x等於30時跳出迴圈,後面都不列印了
         }
         System.out.print( x );
         System.out.print("\n");
      }
   }
}

continue

跳過當前這次迴圈,執行下一次迴圈。

示例:

public class Test {
   public static void main(String args[]) {
      int [] numbers = {10, 20, 30, 40, 50};
 
      for(int x : numbers ) {
         if( x == 30 ) {
        	continue;  // 不會列印30,但是會繼續列印後面元素
         }
         System.out.print( x );
         System.out.print("\n");
      }
   }
}

break和continue可以從字面意思來區分,break中斷迴圈,continue繼續下次迴圈。

條件語句

if

if(布林表示式)
{
   //如果布林表示式為true將執行的語句
}

示例:

public class Test {
 
   public static void main(String args[]){
      int x = 10;
 
      if( x < 20 ){
         System.out.print("這是 if 語句");
      }
   }
}

if else

if(布林表示式){
   //如果布林表示式的值為true
}else{
   //如果布林表示式的值為false
}

示例:

public class Test {
 
   public static void main(String args[]){
      int x = 30;
 
      if( x < 20 ){
         System.out.print("這是 if 語句");
      }else{
         System.out.print("這是 else 語句");
      }
   }
}

也可以跟多個if else:

if(布林表示式 1){
   //如果布林表示式 1的值為true執行程式碼
}else if(布林表示式 2){
   //如果布林表示式 2的值為true執行程式碼
}else if(布林表示式 3){
   //如果布林表示式 3的值為true執行程式碼
}else {
   //如果以上布林表示式都不為true執行程式碼
}

示例:

public class Test {
   public static void main(String args[]){
      int x = 30;
 
      if( x == 10 ){
         System.out.print("Value of X is 10");
      }else if( x == 20 ){
         System.out.print("Value of X is 20");
      }else if( x == 30 ){
         System.out.print("Value of X is 30");
      }else{
         System.out.print("這是 else 語句");
      }
   }
}

巢狀的if else

if(布林表示式 1){
   ////如果布林表示式 1的值為true執行程式碼
   if(布林表示式 2){
      ////如果布林表示式 2的值為true執行程式碼
   }
}

示例:

public class Test {
 
   public static void main(String args[]){
      int x = 30;
      int y = 10;
 
      if( x == 30 ){
         if( y == 10 ){
             System.out.print("X = 30 and Y = 10");
          }
       }
    }
}

switch case

switch(expression){
    case value :
       //語句
       break; //可選
    case value :
       //語句
       break; //可選
    //你可以有任意數量的case語句
    default : //可選
       //語句
}
  • expression:變數或返回變數的方法,變數型別可以是byte、short、int或char,以及String型別。
  • value:字串常量或字面量,且與表示式的變數型別相同。
  • break:可選,有break時會中斷後續匹配跳出switch語句,沒有break時會繼續執行後面的case。
  • default:當所有case都沒有匹配到時,會執行default語句,一般放在最後的位置。

示例:

public class Test {
   public static void main(String args[]){
      //char grade = args[0].charAt(0);
      char grade = 'C';
 
      switch(grade)
      {
         case 'A' :
            System.out.println("優秀"); 
            break;
         case 'B' :
         case 'C' :
            System.out.println("良好");
            break;
         case 'D' :
            System.out.println("及格");
            break;
         case 'F' :
            System.out.println("你需要再努力努力");
            break;
         default :
            System.out.println("未知等級");
      }
      System.out.println("你的等級是 " + grade);
   }
}

Number類

Java是純物件導向程式語言,為了以物件的方式使用內建資料型別,比如byte、int、long、double等,Java對它們進行了封裝,封裝後的類稱為包裝類。這裡的封裝一般也叫做裝箱,反之叫做拆箱。

所有的數字包裝類,都是抽象基類Number的子類,包括Byte、Short、Integer、Long、Float、Double。

示例:

public class Test{
   public static void main(String[] args){
      Integer x = 5;  // 裝箱
      x =  x + 10;  // 拆箱
      System.out.println(x); 
   }
}

Math類

為了支援數學運算,Java提供了Math類,可以進行指數、對數、平方根等數學運算。

示例:

public class Test {  
    public static void main (String []args)  
    {  
        System.out.println("90 度的正弦值:" + Math.sin(Math.PI/2));  
        System.out.println("0度的餘弦值:" + Math.cos(0));  
        System.out.println("60度的正切值:" + Math.tan(Math.PI/3));  
        System.out.println("1的反正切值: " + Math.atan(1));  
        System.out.println("π/2的角度值:" + Math.toDegrees(Math.PI/2));  
        System.out.println(Math.PI);  
    }  
}

對於四捨五入,Math提供了round、floor、ceil三個方法:

  • round:四捨五入
  • floor:向下取整
  • ceil:向上取整(返回double型別)

示例:

基本型別與包裝類區別

  1. 基本型別不是物件,不需要new關鍵字建立,包裝類需要使用new關鍵字建立物件。
  2. 儲存方式不同,基本型別的值存在堆疊中,包裝類的例項存在堆中。
  3. 初始值不同,包裝類的初始值為null,基本型別視具體型別而定,比如int初始值為0,boolean初始值為false。
  4. 有些場景下只能使用包裝類,比如與集合類互動,使用泛型和反射呼叫函式,某個欄位允許null值,就只能使用包裝類。

Character類

Character用於對單個字元進行操作。

我們知道Java內建了資料型別char,但物件導向的Java在實際處理過程中需要的是物件,於是包裝類Character就被設計了出來。

建立物件程式碼如下:

Character ch = new Character('a');

也可以利用裝箱簡寫程式碼:

Character ch = 'a';

Character類具有以下方法:

String類

字串在任何程式語言都是應用非常多的,Java提供了String類來對字串進行操作。

建立字串有兩種方式:

簡單方式

String str = "Runoob";

new關鍵字

String str2=new String("Runoob");

它們的區別在於,前者建立的字串存放在公共池中,後者存放在堆上:

// 簡單方式 公共池
String s1 = "Runoob";             
String s2 = "Runoob";             
String s3 = s1;

// new關鍵字 堆
String s4 = new String("Runoob");   
String s5 = new String("Runoob");

如下圖所示:

String有3個常用方法:

獲取長度

String site = "www.runoob.com";
int len = site.length();

連線字串

// 呼叫方法
"我的名字是 ".concat("Runoob");
// “+”操作符
"Hello," + " runoob" + "!"

建立格式化字串

String fs;
fs = String.format("浮點型變數的值為 " +
                   "%f, 整型變數的值為 " +
                   " %d, 字串變數的值為 " +
                   " %s", floatVar, intVar, stringVar);

StringBuilder類

String建立的字串物件是不能修改的,如果想修改,那麼需要用到StringBuffer和StringBuilder類。

StringBuilder相對於StringBuffer來說有速度優秀,所以大多數時候使用StringBuilder即可。如果想要保證執行緒安全,那麼只能使用StringBuffer。

StringBuilder示例:

public class RunoobTest{
    public static void main(String args[]){
        StringBuilder sb = new StringBuilder(10);
        sb.append("Runoob..");
        System.out.println(sb);  
        sb.append("!");
        System.out.println(sb); 
        sb.insert(8, "Java");
        System.out.println(sb); 
        sb.delete(5,8);
        System.out.println(sb);  
    }

StringBuffer類

示例:

public class Test{
  public static void main(String args[]){
    StringBuffer sBuffer = new StringBuffer("菜鳥教程官網:");
    sBuffer.append("www");
    sBuffer.append(".runoob");
    sBuffer.append(".com");
    System.out.println(sBuffer);  
  }
}

陣列

Java中的陣列是用來儲存固定大小的同型別元素。

宣告方式:

dataType[] arrayRefVar;

建立陣列:

arrayRefVar = new dataType[arraySize];

宣告和建立可以一行程式碼搞定:

dataType[] arrayRefVar = new dataType[arraySize];

在建立時同時初始化值:

dataType[] arrayRefVar = {value0, value1, ..., valuek};

或者建立匿名陣列:

System.out.println(Arrays.toString(new int[]{3, 1, 2, 6, 4, 2}));

陣列是通過索引來訪問元素的,索引值從0到arrayRefVar.length-1。

可以使用for迴圈來遍歷陣列,比如:

public class TestArray {
   public static void main(String[] args) {
      double[] myArray = {1.9, 2.9, 3.4, 3.5};
 
      // 列印所有陣列元素
      for (int i = 0; i < myArray.length; i++) {
         System.out.println(myArray[i] + " ");
      }
      // 計算所有元素的總和
      double total = 0;
      for (int i = 0; i < myArray.length; i++) {
         total += myArray[i];
      }
      System.out.println("Total is " + total);
      // 查詢最大元素
      double max = myArray[0];
      for (int i = 1; i < myArray.length; i++) {
         if (myArray[i] > max) max = myArray[i];
      }
      System.out.println("Max is " + max);
   }
}

也能使用for each在不使用下標的情況下遍歷陣列:

for(type element: array)
{
    System.out.println(element);
}

比如:

public class TestArray {
   public static void main(String[] args) {
      double[] myArray = {1.9, 2.9, 3.4, 3.5};
 
      // 列印所有陣列元素
      for (double element: myArray) {
         System.out.println(element);
      }
   }
}

前面介紹的都是一維陣列,除了一維陣列,還有多維陣列,比如:

String[][] str = new String[3][4];
int[][] a = new int[2][3];

java.util.Arrays類提供了很多方法來運算元組,這些方法都是靜態的。比如:

  • toString:轉換為字串。
  • fill:給陣列賦值。
  • sort:對陣列排序。
  • equals:比較陣列。
  • binarySearch:對排序好的陣列進行二分查詢。

方法

Java中沒有函式的概念,只有方法這一說法。但實際上他們的作用是一模一樣的,都是把一段程式碼進行封裝後呼叫。

方法的命名規則

Java中的方法採用駝峰命名法,第一個單詞首字母小寫,後面每個單詞首字母均大寫,比如addPerson。

方法定義

image-20220210202818556

main方法

public static void main(String[] args) {
	int i = 5;
	int j = 2;
	int k = max(i, j);
	System.out.println( i + " 和 " + j + " 比較,最大值是:" + k);
}

main方法的頭部是不變的,帶修飾符public和static,返回void型別值,方法名字是main,此外帶一個String[]型別引數args。

void

void是Java基本資料型別之一,表明方法沒有返回值。

值傳遞

Java方法的引數傳遞都是值傳遞。如果引數是基本型別,傳遞的值是基本型別字面量的拷貝。如果引數是物件,傳遞的值是物件引用的拷貝。

構造方法

構造方法和類名一模一樣,是一種特殊的方法,沒有返回值,在物件初始化時呼叫。一個類可以有多個構造方法,Java會根據引數進行匹配。比如:

// 一個簡單的建構函式
class MyClass {
    int x;

    // 建構函式
    MyClass() {
        x = 10;
    }

    // 建構函式
    MyClass(int i) {
        x = i;
    }
}

構造方法可以不用顯式定義,Java會預設定義一個,一旦你定義了自己的構造方法,預設構造方法就會失效。預設構造方法的訪問修飾符和類的訪問修飾符相同,類為public構造方法也是public,類為protected構造方法也是protected。

finalize()

finalize()方式是建構函式的逆向,在物件銷燬時呼叫,比如:

public class FinalizationDemo {  
  public static void main(String[] args) {  
    Cake c1 = new Cake(1);  
    Cake c2 = new Cake(2);  
    Cake c3 = new Cake(3);  
      
    c2 = c3 = null;  
    System.gc(); //呼叫Java垃圾收集器
  }  
}  
 
class Cake extends Object {  
  private int id;  
  public Cake(int id) {  
    this.id = id;  
    System.out.println("Cake Object " + id + "is created");  
  }  
    
  protected void finalize() throws java.lang.Throwable {  
    super.finalize();  
    System.out.println("Cake Object " + id + "is disposed");  
  }  
}

可變引數

typeName... parameterName

一個方法中只能有一個可變引數,並且必須放在最後。比如:

public class VarargsDemo {
    public static void main(String args[]) {
        // 呼叫可變引數的方法
        printMax(34, 3, 3, 2, 56.5);
        printMax(new double[]{1, 2, 3});
    }
 
    // 可變引數
    public static void printMax( double... numbers) {
        if (numbers.length == 0) {
            System.out.println("No argument passed");
            return;
        }
 
        double result = numbers[0];
 
        for (int i = 1; i <  numbers.length; i++){
            if (numbers[i] >  result) {
                result = numbers[i];
            }
        }
        System.out.println("The max value is " + result);
    }
}

異常處理

Java的異常檢測格外的嚴格,如果沒有合適的處理異常,有可能程式碼都無法編譯。Java異常類如下圖所示:

img

Throwable類有兩個類Error和Exception,圖中也列舉了幾個常見的子類,比如OutOfMemoryError記憶體溢位、NullPointerException空指標異常等。

捕獲異常

try
{
   // 程式程式碼
}catch(ExceptionName e1)
{
   //Catch 塊
}

示例:

// 檔名 : ExcepTest.java
import java.io.*;
public class ExcepTest{
 
   public static void main(String args[]){
      try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}

多重捕獲

一個try後面可以跟多個catch:

try{
   // 程式程式碼
}catch(異常型別1 異常的變數名1){
  // 程式程式碼
}catch(異常型別2 異常的變數名2){
  // 程式程式碼
}catch(異常型別3 異常的變數名3){
  // 程式程式碼
}

示例:

try {
    file = new FileInputStream(fileName);
    x = (byte) file.read();
} catch(FileNotFoundException f) { // Not valid!
    f.printStackTrace();
    return -1;
} catch(IOException i) {
    i.printStackTrace();
    return -1;
}

throws/throw

throws放在方法尾部用來丟擲異常,throw放在方法中用來丟擲異常。

import java.io.*;
public class className
{
  public void deposit(double amount) throws RemoteException
  {
    // Method implementation
    throw new RemoteException();
  }
  //Remainder of class definition
}

一個方法可以丟擲多個異常:

import java.io.*;
public class className
{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException
   {
       // Method implementation
   }
   //Remainder of class definition
}

finally

無論是否發生異常,finally程式碼塊中的程式碼總會被執行。finally程式碼塊不是必須而是可選的。

try{
  // 程式程式碼
}catch(異常型別1 異常的變數名1){
  // 程式程式碼
}catch(異常型別2 異常的變數名2){
  // 程式程式碼
}finally{
  // 程式程式碼
}

示例:

public class ExcepTest{
  public static void main(String args[]){
    int a[] = new int[2];
    try{
       System.out.println("Access element three :" + a[3]);
    }catch(ArrayIndexOutOfBoundsException e){
       System.out.println("Exception thrown  :" + e);
    }
    finally{
       a[0] = 6;
       System.out.println("First element value: " +a[0]);
       System.out.println("The finally statement is executed");
    }
  }
}

自定義異常

繼承Exception或RuntimeException類可以自定義異常,比如:

// 檔名InsufficientFundsException.java
import java.io.*;
 
//自定義異常類,繼承Exception類
public class InsufficientFundsException extends Exception
{
  //此處的amount用來儲存當出現異常(取出錢多於餘額時)所缺乏的錢
  private double amount;
  public InsufficientFundsException(double amount)
  {
    this.amount = amount;
  } 
  public double getAmount()
  {
    return amount;
  }
}

定義好以後就可以throw new InsufficientFundsException(needs);丟擲異常,然後再try{} catch(InsufficientFundsException e){} 捕獲異常。

參考資料:

JDK維基百科 https://zh.wikipedia.org/zh-hans/JDK

Java菜鳥教程 https://www.runoob.com/java/java-tutorial.html

Java 到底是值傳遞還是引用傳遞?https://www.zhihu.com/question/31203609

相關文章