Java 學(xué)習(xí)基礎(chǔ)篇 ---- Java面向?qū)ο缶幊?/h2>

一、面向?qū)ο蟾拍?/h2>

OOP:Object Oriented Programming class和instance是“模版”和“實例”的關(guān)系:
類:class,對象模版
實例:instance,具體對象 class用字段(field)封裝了數(shù)據(jù),不同的instance擁有各自獨立的字段(field)
通過變量.字段名訪問某個字段(field)
指向instance的變量都是引用變量

二、數(shù)據(jù)封裝

一個 class 可以包含多個 field,直接把 field 用public暴露給外部可能破壞了封裝,我們可以用 private關(guān)鍵字 修飾 field 進(jìn)而拒絕外部訪問。
外部代碼通過定義 public方法可以間接的修改 private關(guān)鍵字 修飾的 field。
通過 變量.方法名() 來調(diào)用實例方法。
通過 方法 訪問實例字段更安全。

public class Person{
    private String name;
    private int age;
    public String address;

    public void setName(String name){
        this.name = name;
    }
    public String getName() {
        return this.name; 
    }
}
Person ming = new Person();
ming.address = "北京";     // 可以賦值
ming.name = "小明";  // 編譯錯誤
ming.age = 12;   // 編譯錯誤
ming.setName(" 小明  ");
System.out.println(ming.getName());   // "小明"

(一)方法定義

1、修飾符:public、private、
2、方法返回值:有返回值的方法要寫上返回值類型,沒有返回值的方法 用void 來表示,void 表示不返回任何值(注意和返回null不同)
3、方法名稱:首字母小寫,后面的單詞首字母大寫;
4、方法參數(shù):方法名稱后的 () 內(nèi)寫入?yún)?shù)及參數(shù)類型列表,如果沒有參數(shù)則空著,如果有多個參數(shù)則需要用逗號隔開每一個參數(shù)的類型及變量,方法參數(shù)可以是基本類型參數(shù),也可以是引用類型參數(shù)。

public class Person{
    private String name;
    private int age;
    public String address;

    public String getName() {
        return this.name; 
    }

    public void setName(String name){
        if (name == null){
            throw new NullPointException();
        }
        this.name = name.trim();
        return;   // 可以省略,因為 void 
    }

    public void retName(String name_1, String name_2){
        // Todo
    }
}

5、方法內(nèi)部可以使用隱式變量 this,this指向當(dāng)前實例,this.field 可以訪問當(dāng)前實例的字段。
6、調(diào)用方法:實例變量.方法名(參數(shù)),可以忽略方法返回值。

Person ming = new Person();
ming.setName("  小明");   // 沒有返回值
String s = ming.getName();   // 返回值為 String

7、可以定義 private 方法,外部代碼不可以訪問 private 方法,內(nèi)部代碼可以調(diào)用自己的 private 方法,外部代碼可以通過 public 方法間接調(diào)用 private 方法。

public class Person{
    private String name;
    private int age;
    public String getBirth() {
        retrun calcBirth(2016);
    }
    private int calcBirth (int currentYear){
        return currentYear - this.age;
    }
}

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

1、構(gòu)造方法可以在創(chuàng)建對象實例時初始化對象實例
2、構(gòu)造方法名就是類名
3、構(gòu)造方法的參數(shù)沒有限制
4、構(gòu)造方法沒有返回值,也沒有 void
5、必須使用 new操作符 調(diào)用構(gòu)造方法

public class Person{
    private String name;
    private int age;
    public Person(String name, int age) {      // 構(gòu)造方法 Person
        this.name = name;
        this.age = age;
    }
}

6、如果一個類沒有定義構(gòu)造方法,編譯器會自動生成一個默認(rèn)的構(gòu)造方法(無參數(shù),無執(zhí)行語句)

public class Person{
    private String name;     // = null
    private int age;            // = 0
    private String address = "北京";
    public Person() {        // 編譯器生成的默認(rèn)構(gòu)造方法
    }
}

7、如果自定義了構(gòu)造方法,編譯器就不再自動創(chuàng)建默認(rèn)構(gòu)造方法
8、 構(gòu)造方法參數(shù)的初始化順序:先初始化字段,沒有賦值的字段初始化為默認(rèn)值(基本類型=0;引用類型=null),再執(zhí)行構(gòu)造方法的代碼

public class Person{
    private String name;     // = null
    private int age;            // = 0
    private String address = "北京";
    public Person(String name, int age, Sting address) {       // 三個參數(shù),創(chuàng)建實例時傳入
        this.name = name; 
        this.age = age;
        this.address = address;
    }
}

9、一個類的構(gòu)造方法可以有多個,通過創(chuàng)建實例s時傳入的參數(shù)個數(shù)、參數(shù)類型來判斷具體調(diào)用了哪個構(gòu)造方法

public class Person{
    private String name;     // = null
    private int age;            // = 0
    private String address = "北京";
    public Person(String name, int age, Sting address) {       // 構(gòu)造方法一
        this.name = name; 
        this.age = age;
        this.address = address;
    }
    public Person(String name){       // 構(gòu)造方法二
        this.name = name; 
        System.out.println("hello world")
    }
    public Person(){             // 構(gòu)造方法三
        System.out.println("hello")
    }
}

10、一個構(gòu)造方法可以調(diào)用其他構(gòu)造方法,便于代碼復(fù)用,調(diào)用其他構(gòu)造方法的語法是 this(..)

public class Person{
    private String name;     // = null
    private int age;            // = 0
    private String address = "北京";
    public Person(String name, int age, Sting address) {      // 構(gòu)造方法一
        this.name = name; 
        this.age = age;
        this.address = address;
    }
    public Person(String name){        // 構(gòu)造方法二
        this(name,10,"北京")
    }
    public Person(){       // 構(gòu)造方法三
        this("Andy")
    }
}

(三)方法重載

1、方法重載入是指多個方法的方法名相同,但是各自的參數(shù)不同(參數(shù)個數(shù),參數(shù)類型,參數(shù)位置),方法返回值類型通常是相同的。
2、方法重載的目的是使相同功能的方法使用同一方法名,以便于調(diào)用

public class Hello {
    public void indexOf (String name){
    }
    public void indexOf (int age){
    }
    public void indexOf (int age, String name){
    }
    public void indexOf (String name, int age){
    }
}
public class Main{
    public static void main(String[] agers){
        Hello s = new Hello();
        int n1 = s. indexOf('t');
        int n2 = s. indexOf('st', 20);
    }
}

三、繼承多態(tài)

(一)繼承

1、繼承使用關(guān)鍵字 extends,子類 Student 獲得了父類 Person 的所有功能,Student 只需要編寫新增的功能。
2、如果定義的類沒有寫 extends 關(guān)鍵字,則該類繼承自 object 類。
3、Java 只允許 class 繼承自一個類,不與許同時繼承自多個類,即一個類有且僅有一個父類。

public class Person{
    private String name;
    private int age;
    publicString getName(){
        return name
    }
    public void setName(String name){
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void run(){
        System.out.println(name +  " is running!");
    }
}
public class Student extends Person {
    private int score;
    public void setScore(int score){
        return score;
    }
    public int getScore(){
        this.score = score;
    }
}
public class Main{
    public static void main(String[] args){
        Person p = new Person();
        Student s = new Student();
        p.setName("Xiao Ming");
        s.setName("Xiao Hong");
        p.run();     // Xiao Ming is running!
        s.run();     // Xiao Hong is running!
    }
}

4、Person 類定義的 private 字段無法被子類訪問
5、Person 類定義的 protected 修飾的字段可以被子類訪問。即 protected關(guān)鍵字 把字段和方法的訪問權(quán)限控制在了繼承樹內(nèi)部。

public class Person {
   private String name;
   private int age;
   protected String hight;
   public void run() {
   }
}
public class Student extends Person{
    public String hello(){
        return "Hello," + this. name;             // ERROR!
    }
    public String hello(){
        return "Hello," + this. hight;             // ok
    }
}

6、java 語言規(guī)定編寫子類的構(gòu)造方法時,必須在第一行調(diào)用父類的構(gòu)造方法(使用 super() 語句調(diào)用),如果沒有調(diào)用 super() 方法,編譯器會默認(rèn)的幫助我們調(diào)用 super() ; 但是如果父類沒有默認(rèn)的構(gòu)造方法,即父類顯式的實現(xiàn)了構(gòu)造方法,則子類需要在自身的構(gòu)造方法中顯式(手動)調(diào)用 super() 方法,并傳入父類需要的參數(shù)。實例如下:

public class Person {
    public String name;
    public int age;
    public Person(String name){        // 顯式的實現(xiàn)帶一個參數(shù)的構(gòu)造方法
        System.out.println("create Person");
    }
}
public class Student extends Person{
    public Student(){
        super("小紅");         // 父類 Person 是顯式構(gòu)造的構(gòu)造方法,所以子類 Student 需要顯式調(diào)用 super(),并傳入?yún)?shù)
        System.out.println(" create student");
    }
}

7、向上轉(zhuǎn)型:可以對實例變量進(jìn)行向上轉(zhuǎn)型(upcasting),向上轉(zhuǎn)型把子類型安全地變?yōu)楦映橄蟮念愋?。例?Student 類實例對象 轉(zhuǎn)型為 Person 類實例對象。

Person p = new Person();
Student s = new Student();
Person ps = new Student();    // upcasting   ps 是 Person 類型
Object o1 = p;    // upcasting
Object o2 = s;    // upcasting

8、向下轉(zhuǎn)型:可以對實例變量進(jìn)行向下轉(zhuǎn)型(downcasting), 向下轉(zhuǎn)型把抽象的類型變成一個具體的子類型。

Person p = new Student()
Student s = (Student) p;   // downcasting 

向下轉(zhuǎn)型很可能報錯:ClassCastException

Person p = new Person()
Student s = (Student) p;   // ClassCastException

9、instanceof 操作符:判斷實例對象的類型

Person p = new Person();
System.out.println(p instanceof Person);      // true
System.out.println(p instanceof Student);     // false

(二)多態(tài)

1、子類覆寫父類的方法是覆寫(Override),覆寫的方法使用 @Override 修飾,該修飾非必須,但是可以讓編譯器幫助檢查是否進(jìn)行正確的覆寫,如下:

public class Person{
    public void run(){
    }
}
public class Student extends Person{
    @Override           // 可省略
    public void run(){
    }
    @Override           // Compile error!  因為沒有進(jìn)行正確覆寫
    public void run( String name){
    }
}
Person p = new Student();         
p.run();      

2、方法簽名如果不同就不是 Override,而是創(chuàng)建了一個新方法,如下:

public class Person {
    public void run(){
    }
}
public class Student extends Person {         
    public void run(String s){           // 方法簽名不同(有參數(shù)),所以不是覆寫,而是創(chuàng)建了一個新的方法,此處省略了 @Override 關(guān)鍵字
    }
}

3、java 中引用變量的聲明類型可能與其實際類型不符
4、多態(tài)概念:實例對象的方法調(diào)用總是對應(yīng)實際類型,即Java 的實例方法調(diào)用是基于運行時實際類型的動態(tài)調(diào)用
5、多態(tài)定義:指針對某個類型的方法調(diào)用,其真正執(zhí)行的方法取決于運行時實際類型的方法。所以我們對某個類型調(diào)用某個方法,執(zhí)行的方法可能是某個子類的覆寫方法。利用多態(tài)的允許添加更多類型的子類的特性,實現(xiàn)功能的擴展。

public class Person{
    public void run(String name){
        System.out.println(name + " is running")
    }
}
public class Student extends Person{
    @Override           // 可省略
    public void run(String name){
        System.out.println("Student " + name + " is running")
    }
}
public class Main{
    public static void main(String[] args){
        Person p = new Person("Xiao Ming");
        Person s = new Student(("Xiao Hang");
        p.run();        // 調(diào)用的是 Person 類型的 run() 方法
        s.run();      // 調(diào)用的是實際類型 Student 的 run() 方法
    }
}

6、所有的類都是從 Object 類繼承下來的,是在 Object 類的基礎(chǔ)上使用多態(tài)實現(xiàn)了功能的擴展。例如:toString() 方法、equals() 方法、hashCode() 方法。

public class Person{              // 在子類 Person 中對父類 Object 的各個方法進(jìn)行覆寫
    @Override
    public String toString(){         // toString() 方法:把接口 instance 輸出為 String
    }
    @Override
    public boolean equals(Object o){       // equals() 方法: 判斷兩個接口 instance 是否邏輯相等
    }
    @Override
    public int hashCode(){    // hashCode() 方法:計算一個接口 instance 的哈希值
    }
}

7、super 方法可以調(diào)用父類的被覆寫 Override 的方法,如下:

public class Person{
    private String name;
    public String hello(){
        return "Hello, " + name;
    }
}
public Student extends Person{
    @Override
    public String hello(){
        return super.hello() + "!";          // 此處使用 super.hello() 調(diào)用父類的 hello() 方法,返回 “Hello,” + name 的執(zhí)行結(jié)果
    }
}

8、 final 關(guān)鍵字:當(dāng)我們定義一個類的方法時如果不希望該方法被子類覆寫,可以使用 final 關(guān)鍵字修飾。
9、使用 final 關(guān)鍵字修飾的類不能被繼承;使用 final 關(guān)鍵字修飾的方法不能被Override;使用 final 關(guān)鍵字修飾的字段 field 在初始化后不能被修改;

public class Person{
    public final void setName(String name){
    }
}
public final class Student extends Person{
    private final int score;
}

四、抽象類和接口

(一) 抽象類

1、抽象方法:如果一個class 定義了方法,但沒有具體執(zhí)行代碼,這個方法就是抽象方法;
(1)抽象方法使用 abstract 關(guān)鍵字修飾;
(2)抽象方法沒有任何執(zhí)行語句;
(3)因為無法執(zhí)行抽象方法,因此實現(xiàn)抽象方法的類必須使用 abstract 關(guān)鍵字修飾為抽象類;
(4)抽象類無法實例化,但可以被繼承;
(5)抽象類強迫其子類實現(xiàn)其定義的抽象方法,否則編譯錯誤;

public abstract class Person{
    public abstract void run();         // 定義一個抽象方法 run(),和一個抽象類 Person()
}
Person p = new Person();        // 編譯錯誤, 因為抽象類無法實例化
Person s = new Student();       // OK       Student類 繼承了 Person類
Person t = new Teacher();       // OK        Teacher類 繼承了 Person類
// 調(diào)用抽象方法實現(xiàn)多態(tài):
s.run();
t.run();

2、面向抽象編程:
(1)不關(guān)心父類 Person類型 對象的具體類型
(2)不關(guān)心新的子類是如何實現(xiàn)抽象方法 (run方法)的

public abstract class Person{
    public abstract void run();
}
public class Student extends Person{
    @Override
    public voide run() {
    }
}
public class Teacher extends Person{ 
    @Override
    public void run() {
    }
}
Person s = new Student();
Person t = new Teacher();
s.run()
t.run()

3、總結(jié):
抽象方法定義了子類必須實現(xiàn)的接口規(guī)范
定義了抽象方法的類就是抽象類
從抽象類繼承的子類必須實現(xiàn)抽象方法
如果不實現(xiàn)抽象方法,則該子類仍是一個抽象類

(二) 接口 --- Interface

1、如果一個抽象類沒有字段,所有方法全部是抽象方法,就可以把該抽象類改寫為接口(interface),可以使用關(guān)鍵字 interface 來聲明一個接口。

public interface Person{
    // public abstract void run();              // 接口定義的方法默認(rèn)是 public abstract (不需要寫)
    void run();
}

2、interface 是 Java 內(nèi)置的純抽象接口,實現(xiàn) interface 使用 implements。

public class Student implements Person{
    @Override
    public void run(){}
}

3、一個類可以同時實現(xiàn)多個 interface。

public class Robot implements Hello, Comparable{
}

4、一個類如果想實現(xiàn)某個接口,子類必須實現(xiàn)該接口中所定義的全部方法,如果接口中方法是使用 default 關(guān)鍵字定義的,則該方法默認(rèn)被子類實現(xiàn)了

// 接口
public interface Shape{
    double area();              //  繼承時 area方法 需要顯式實現(xiàn)
    default double perimeter(){              // default 關(guān)鍵字修飾的方法,繼承時默認(rèn)實現(xiàn)
        return 0;
    }
}
// 實現(xiàn)接口的子類
public class Rect implements Shape{
    private final double width;
    private final double height;
    public Rect(double width, double height){
        this.width = width;
        this.height = height;
    }
    @Override
    public double area(){
        return width * height
    }
}
public class Main{
    public static void main(String[] args){
        Shape s1 = new Rect(200, 100);
        System.out.println(s1.area());
    }
}

5、一個 interface 可以繼承自另一個 interface,interface 之間的繼承使用 extends 關(guān)鍵字

public interface Person {
    String getName();
}
public interface Student extends Person{
    String getSchool();
}
public class PrimaryStudent implements Student{
    @Override
    public String getName(){
    }
    @Override
    public String getSchool(){
    }
}

6、interface 的繼承相當(dāng)于擴展了 interface(接口)的方法

(三) 抽象類 vs 接口

1、合理設(shè)計 interface 和 abstract class 的繼承關(guān)系:公共邏輯放在 abstract class 中。
2、類可以實現(xiàn)多個接口。
3、接口也是數(shù)據(jù)類型,適用于向上轉(zhuǎn)型和向下轉(zhuǎn)型。
4、接口不能定義實例字段。
5、接口可以定義 default 方法(JDK >= 1.8)

五、包和classpath

(一) 靜態(tài)字段和靜態(tài)方法

1、用 static 修飾的字段稱為靜態(tài)字段,普通的字段在每個實例中都有自己的一個獨立"空間",靜態(tài)字段只有一個共享"空間"。
2、對于一個類的所有實例,都共享一個靜態(tài)字段。
3、不推薦用實例變量訪問靜態(tài)字段。
4、推薦用類名訪問靜態(tài)字段。
5、可以把靜態(tài)字段理解為描述 class 本身的字段(非實例字段)。

public class Person{
    public String name;
    public int age;
    public static int number = 100;       // 定義一個靜態(tài)字段 number
}
Person ming = new Person();
Person hong = new Person();
ming.number = 99;            // 通過 實例變量 訪問靜態(tài)字段,不推薦
System.out.println(hong.number);       // 99
Person.number = 88;                     // 使用 類名 調(diào)用靜態(tài)變量 
System.out.println(Person.number);    // 88     

6、用 static 修飾的方法稱為靜態(tài)方法,調(diào)用實例方法必須通過實例變量,調(diào)用靜態(tài)方法不需要實例變量,可直接使用類名調(diào)用(靜態(tài)方法類似于其他編程語言中的函數(shù))。

public class Person{
    private String name;
    private static int number = 100;
    pulic static viod setNumber(int num){
        number = num;
    } 
}
Person.setNumber(99);

7、靜態(tài)方法不能訪問 this 變量。
8、靜態(tài)方法不能訪問實例字段。
9、靜態(tài)方法可以訪問靜態(tài)字段、及其他靜態(tài)方法。
10、Java程序的入口 main() 也是靜態(tài)方法。

(二) 包

1、Java 定義了名字空間:包,包名 + 類名 = 完整類名。
2、包(package) 可以是多層結(jié)構(gòu):java.util.Arrays。
3、包沒有父類 / 子類關(guān)系:java.util 和 java.util.zip 是不同的包,兩者沒有任何關(guān)系。
4、包作用域:不用 public、protected、private修飾的字段和方法就是包作用域。
5、位于同一個包的類,可以訪問包作用域的字段和方法。

package hello;
public class World{
    static int findMax(int[] ns){
    }
}
package hello;
public class Map{
    int price;
    void setPrice(int price)
}

6、包的引用:

package hello;
import java.util.Arrays;

public class World{
    public int findMin(int[] ns){
        Arrays sort(ns);
        return ns[0];
    }
}

(三) 作用域

1、訪問權(quán)限是指在一個類的內(nèi)部,能否引用另一個類以及訪問它的字段和方法。
2、訪問權(quán)限有 public、protected、private 和 package 四種。
(1)定義為 public 的 field、method 可以被其他類訪問;
(2)定義為 private 的 field、method 無法被其他類訪問,但是在類的內(nèi)部可以訪問(即 private 訪問權(quán)限限定在了 class 的內(nèi)部);
(3)private 還可以修飾 class,定義為 private 的 class 無法被其他類訪問
(4)訪問 private class 被限定在外層 class 的內(nèi)部,定義在一個 class 內(nèi)部的 class 稱為 內(nèi)部類(inner class)。

package abc;

public class Hello{
    public void hello(){
        Inner inner = null;
    }
    private class Inner{         // 定義一個內(nèi)部類   Inner
    }
}

(5)protected 作用于繼承關(guān)系,定義為 protected 的字段和方法可以被子類訪問

package abc;

public class Hello{
    protected void hi(){
    }
}
package xyz;

class World extends Hello {
     void foo(){
        Hello h = new Hello();
        h.hi();
    }
}

(6)包作用域(package) 是指一個類允許訪問同一個 package 的沒有 public、private 修飾的 class,以及沒有 public、protected、private 修飾的 字段和方法。注意:包名必須完全一致

package abc;

class Hello {
    void hi() {
    }
}
package abc;

class Main {
    void foo()[
        Hello h = new Hello();
        h.hi()
    }
}

3、最佳實踐:最小化暴露對外方法,即盡量少使用 public 。
4、局部變量:在方法內(nèi)部定義的變量稱為局部變量,局部變量作用域由所在語句塊{...}決定。

package abc;

public class Hello{
    void hi(String name){
        String s = name.toLowerCase();
        int len = s.length();
        if (len < 10){
           int p = 10 - len;
           for (int i = 0; i < 10; i++){
               System.out.println(i);
           }
        }
    }
}

5、final 關(guān)鍵字:
(1)final 與訪問權(quán)限不沖突;
(2)用 final 修飾 class 可以阻止被繼承;
(3)用 final 修飾 method 可以阻止被覆寫;
(4)用 final 修飾 field 可以阻止被重新賦值;
(5)用 final 修飾局部變量可以阻止被重新賦值;

package abc;

public class Hello{
    private int n = 0;
    protected void hi(final int t){
        final long i = t;
    }
}

6、一個.java 文件只能包含一個 public class, 但是可以包含多個非 public class。

(四) classpath 和 jar

1、jar 包是 zip 格式的壓縮文件,包含若干 .class 文件。
2、jar 包相當(dāng)于目錄,classpath 可以包含 jar 文件,例如:C:\work\bin\all.jar。
3、查找 com.fiya.Hello 類會在 C:\work\bin\all.jar 文件中搜索 com/fiya/Hello.class。
4、jar 包的其他功能:
(1)jar 包可以包含一個特殊的 /META-INF/MANIFEST.MF 文件,該文件是純文本,可以指定 Main-Class 和其他信息。
(2)jar 包還可以包含其他 jar 包。
5、JVM運行時會自動加載 JDK 自帶的 class。JDK自帶的 class 被打包在 rt.jar 中。

六、Java核心類

(一) 字符串和編碼

1、String 可以使用 "" 來直接創(chuàng)建,創(chuàng)建后內(nèi)容不可變。

String s1 = "hello";        // 創(chuàng)建 String 方法一
String s2 = new String("world");        // 創(chuàng)建 String 方法二

2、字符串常用操作:
(1)使用 equals() 判斷字符串是否相等,忽略大小寫 equalsIgnoreCase(String)

String s = "hello";
s.equals("Hello");    // false
s.equalsIgnoreCase("Hello")     //  true

(2)是否包含字符串:boolean contains(CharSequence)

String s = "hello world";
s.contains("ll");   // true

(3)查找字符串位置:int indexof(String) 和 int lastIndexof(String)

String s = "hello world";
s.indexof("ll");     // 從前向后查找  2
s.lastIndexof("l")      // 從后向前查找  9

(4)是否以指定字符串開頭:boolean startsWith(String)

String s = "hello world";
s.startsWith("he");         // true

(5)是否以指定字符串結(jié)尾:boolean endsWith(String)

String s = "hello";
s.endsWith("lo");       // true

(6)移除字符串首尾空白字符:trim(),注意 trim() 不改變字符串內(nèi)容,而是返回新的字符串。

String s = " \t hello \r\n ";
String s2 = s.trim();     // "hello"
s = s.trim();

(7)提取字符串子串:substring()

String s = "hello,world";
s.substring(7);      // "world"
s.substring(1, 5);       // "ello"

(8)大小寫轉(zhuǎn)換:toUpperCase()、toLowerCase()

String s = "heLLo";
s.toUpperCase();        // "HELLO"
s.toLowerCase();        // "hello"

(9)替換子串普通替換:replace(char, char)

String s = "hello";
s.replace('l', 'w');      // "hewwo"
s.replace('l', 'w~');     // "hew~w~o"

(10)替換子串正則表達(dá)式替換:replaceAll(String,String)

String s = "A,,B;C ,D";
s.replaceAll("[\\,\\;\\s]+", ", ");         // "A, B, C, D"

(11)分割字符串:String[] split(String)

String s = "A,,B;C ,D";
String[] ss = s.split("[\\,\\;\\s]+");           // {"A", "B", "C", "D"}

(12)拼接字符串:static String join()

String[] arr = {"A", "B", "C"};
String s = String.join("~~", arr);          // "A~~B~~C"

3、String 類型和 其他任意類型 的轉(zhuǎn)換
(1)把任意數(shù)據(jù)轉(zhuǎn)換為 String 類型:static String valuOf(int)、static String valuOf(boolean)、static String valuOf(Object)

String.valueOf(123);     // "123"
String.valueOf(true);     // "true"
String.valueOf(new Object());   // "java.lang.Object@7852e922"

(2)把 String 類型轉(zhuǎn)換為其它類型:
static int Interger.parseInt(String)

int i = Integer.parseInt("123");      //123

static Interger Interger.valueOf(String)

Integer I = Interger.valueOf("123");

4、String 與 char[] 互相轉(zhuǎn)換:
(1)String 轉(zhuǎn)換為 char[]:char[] toCharArray();

String s = "hello";
char[] cs = s.toCharArray();            // {'h', 'e', 'l', 'l', 'o'}

(2)char[] 轉(zhuǎn)換為 String :new String(char[]);

char[] cs = {'h', 'e', 'l', 'l', 'o'};
String s2 = new String(cs);           // "hello"

5、String和byte[]互相轉(zhuǎn)換(需要指定編碼)
(1)String 轉(zhuǎn)換為 byte[]: byte[] getBytes(String)、byte[] getBytes(Charset)

String s = "hello";
byte[] bs1 = s.getBytes("UTF-8");
byte[] bs2 = s.getBytes(StandardCharsets.UTF_8);

(2)byte[] 轉(zhuǎn)換為 String: new String(byte[], String)、new String(byte[], Charset)

new String(bs1, "UTF-8");
new String(bs2, StandardCharsets.UTF_8);

6、一個中文字符占用2個字節(jié),中文編碼:GB31、GBK、GB8030.
7、全球統(tǒng)一編碼:Unicode。Java使用的就是 Unicode 編碼。

(二) StringBuidler

1、StringBuilder 是可變對象,可以預(yù)分配緩沖區(qū),進(jìn)而實現(xiàn)高效的拼接字符串。

StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < 1000; i++){
    sb.append(String.valueOf(i));
}
String s = sb.toString();

2、StringBuilder 可以進(jìn)行鏈?zhǔn)讲僮鳌?/p>

StringBuilder sb = new Stringbuilder(1024);
String s = sb.append("Ms ").append("name").append("!").insert(0, "Hello, ").toString();

3、編譯器在內(nèi)部自動把多個連續(xù)的 + 號操作優(yōu)化為 StringBuilder 操作。

String s = "Hello, " + "nemw" + "!";

4、Java 還提供了一個和 StringBuilder 接口完全相同的接口 StringBuffer,StringBuffer 是線程安全的,一般沒必要使用。

(三) 包裝類型

1、Java 的屬性包括 基本數(shù)據(jù)類型 和 引用數(shù)據(jù)類型,基本類型不能視為對象,如果我們把一個基本類型賦值為null ,程序會報錯。

int n = null;     // ERROR!   

2、可以對基本類型進(jìn)行包裝,變成一個引用類型(即包裝類型實際上是一個引用類型,只不過其內(nèi)部包含一個基本類型的變量)。

// 定義一個 Integer 類,包含一個實例字段 int
public class Integer {
    private int value;
    public Integer(int value) {
        this.value = value;
    }
}
Integer n = null;
Integer n2 = new Integer(99);

以上是我們手動實現(xiàn)的包裝類型,其實 JDK 已經(jīng)為每種基本類型都創(chuàng)建了對應(yīng)的包裝類型,無需我們手動實現(xiàn):

基本類型                對應(yīng)的引用類型
boolean                  Boolean
byte                        Byte
short                      Short
int                          Integer
long                       Long
float                      Float
double                  Double
char                      Character

3、基本類型int 和 對應(yīng)的引用類型Integer 可以相互轉(zhuǎn)化:

Integer n = new Integer(99);           // 基本類型 轉(zhuǎn)換為 引用類型
int i = n.intValue();                 // 引用類型 轉(zhuǎn)換為 基本類型
Integer n1 = Interger.valueOf("88");      // String類型 轉(zhuǎn)換為 引用類型Interger
String s = n.toString();          // 引用類型Interger   轉(zhuǎn)換為   String類型

特別注意 Integer.getInteger(String) 是從系統(tǒng)環(huán)境中讀取系統(tǒng)變量。
4、編譯器可以自動在 int 和 Integer 之間轉(zhuǎn)型:自動裝箱、自動拆箱

Integer n = 99;            // Integer.valueOf(99)        自動裝箱 int -> Integer
int i = n;          // n.intValue()          自動拆箱 Integer -> int

注意:自動裝箱和自動拆箱只發(fā)生在編譯階段;
裝箱和拆箱會影響執(zhí)行效率;
編譯后的class代碼是嚴(yán)格區(qū)分基本類型和引用類型的;
自動拆箱時:Integer -> int 執(zhí)行時可能會報錯(null 時),即 Integer x = null; int y = x; // NullPointerException
5、Java 的包裝類型定義了一些有用的靜態(tài)變量

Boolean t = Boolean.TRUE;
Boolean f = Boolean.FALSE;
int max = Integer.MAX_VALUE;       // 2147483647
int min = Integer.MIN_VALUE;       // -2147483647
int sizeOfLong = Long.SIZE;        // 64 (bite)
int bytesOfLong = Long.BYTES;       // 8(bytes)

6、整數(shù)和浮點數(shù)包裝類型繼承自 Number,所以我們可以對這些包裝類型進(jìn)行向上轉(zhuǎn)型(變?yōu)?Number 類型),然后使用 Number 類型的一些方法將其轉(zhuǎn)化為任意基本類型:


繼承關(guān)系.png
Number num = new Integer(999)         // 將包裝類型 Integer 向上轉(zhuǎn)型為 Number 類型
byte b = num.byteValue();
int n = num.intValue();
long ln = num.longValue();
float f = num.floatValue();
double d = num.doubleValue();

(四) JavaBean

1、許多 class 的定義都符合:a.若干 private 實例字段、b.通過 public 方法讀寫實例字段。符合以上兩種命名規(guī)范的 class 被稱為 JavaBean,即:
(1)private Type field
(2)public Type getField()
(3)public void setField(Type value)
注意:以上三點中方法名稱大小寫不能改變。

public class Person{
    private String name;
    private int age;

    public String getName(){
    }
    public void setName(String name){
    }

    public int getAge(){
    }
    public void setAge(int age){
    }
}

boolean 字段的讀方法命名為 isXxx():

private boolean child
public boolean isChild() {}     // 讀方法
public void setChild(boolean value){}

2、通常把一組對應(yīng)的 getter 和 setter 方法稱為屬性(Property):
(1) 讀寫屬性都具備:
name 屬性:
有對應(yīng)讀方法 getName()
有對應(yīng)寫方法 setName()

(2) 只有 setter 的屬性稱為只寫屬性(Write-only):
age 屬性:
無對應(yīng)讀方法 getAge()
有對應(yīng)寫方法 setAge()

(3) 只有 getter 的屬性稱為只讀屬性(Read-only):
age 屬性:
有對應(yīng)讀方法 getAge()
無對應(yīng)寫方法 setAge()

(五) 枚舉類型

1、常量的定義
(1)可以使用 enum 關(guān)鍵字定義常量, 使用 enum 關(guān)鍵字定義的常量本身帶有類型,使用 == 比較常量是否相等。
(2)enum 可以定義常量類型,它被編譯器編譯為:final class Xxx extends Enum{...}

public enum Weekday{                // 定義了一些 Weekday 類型的常量
    SUN, MON, TUE, WED;
}
public enum Color {          // 定義了一些 Color 類的常量
    RED, GREEN, BLUE;
}
if (day == Weekday.FRI){
}

enum 定義的類型實際上是 class,繼承自 java.lang.Enum(如下),不能通過 new 創(chuàng)建實例,所有常量都是唯一實例,可以用于 switch 語句

public enum Color{
    RED, GREEN, BLUE;
}
// 編譯器編譯出來的 class:
import java.lang.Enum
public final class Color extends Enum{
    public static final Color RED = new Color();
    public static final Color GREEN = new Color();
    public static final Color BLUE = new Color();
    private Color(){}
}

2、常量的一些使用:
(1)name() 獲取常量定義的字符串,注意不要使用 toString()
(2)ordinal() 返回常量定義的順序(無實質(zhì)意義)

package com.test;
public enum Weekday {
    SUN, MON, TUE, WED, THU, FRI, SAT;
}
package com.test;
public class Main{
    public static void main(String[] args){
        for (Weekday day : Weekday.values()){
            System.out.println(day.name());
        }
        Weekday fri = Weekday.FRI;      // 將常量 FRI 賦值給 fri
        System.out.println(fri.name());       // enum類型 -> String類型
        System.out.println(fri.ordinal());      // 返回常量定義的順序
        System.out.println(Weekday.valueOf("FRI").name());      // String類型 —> enum類型
        Weekday.valueOf("ABC");           // 不存在的常量,會拋出 IllegalArgumentException
    } 
}

(3)構(gòu)造方法申明為 private
(4)可以為enum枚舉類編寫構(gòu)造方法、字段和方法,例如為每個枚舉類型添加一個中文名稱:

package com.test;
public enum Weekday {
    // b. 傳入構(gòu)造方法的參數(shù),繼而調(diào)用構(gòu)造方法
    SUN("星期日"), MON("星期一"), TUE("星期二"), WED("星期三"), THU("星期四"), FRI("星期五"), SAT("星期六");        
    private String chinese;
    private Weekday(String chin){         // a. 使用構(gòu)造方法 初始化 chinese 
        this.chinese = chin;
    }
    public String toChinese() {         // c. 定義 toChinese 方法返回  chinese
        return chinese
    }
}
public class Main{
    public static void main(String[] args){
        Weekday fri = Weekday.FRI;
        System.out.println(fri.toChinese());           // 星期五
    }
}

(六) 常用工具類

1、Math 類:提供類數(shù)學(xué)計算的靜態(tài)方法:
(1)abc / min / max
(2)pow / sqrt / exp / log / log10
(3)sin / cos / tan / asin / acos
(4)常量:PI = 3.14159;E = 2.71828
(5)Math.random() 生成一個隨機數(shù),范圍 0 <= 隨機數(shù) < 1

double x1 = Math.random();
long MIN = 1000;
long MAX = 9000;
double x2 = Math.random() * (MAX - MIN) + MIN;
double r = (long) x2;

(6)Random 對象:Random 對象用來創(chuàng)建偽隨機數(shù)

Random r = new Random();
r.nextInt();       // 生成下一個隨機 int
r.nextLong();    // 生成下一個隨機 long
r.nextFloat();    // 生成下一個隨機 float,介于 0~1
r.nextDouble();    // 生成下一個隨機 double,介于 0~1
r.nextInt(10);     // 生成 0~10 之間的隨機數(shù),不包括 10

(7)為隨機數(shù):給定種子后偽隨機數(shù)算法會生成完全相同的序列,不給定種子時 Random 使用系統(tǒng)當(dāng)前時間戳作為種子。

Random r = new Random(12345);
for (int i = 0; i < 10; i ++){
    System.out.println(r.nextInt(100))
}

2、SecureRandom:生成安全的隨機數(shù)。
3、BigInteger:表示任意大小的整數(shù)。
4、BigDecimal:表示任意精度的浮點數(shù)。
5、BigInteger 和 BigDecimal 都繼承自 Number。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容