1-Java基礎(chǔ)知識(shí)

主要內(nèi)容
1. Java基本功
2. Java面向?qū)ο?/strong>
3. Java核心技術(shù)

1. Java基本功

1.1 Java基礎(chǔ)概念與常識(shí)

1.1.1 JDK和JRE
Java編譯全過程

JDK是Java Development Kit警儒,它是功能齊全的 Java SDK训裆。它擁有 JRE 所擁有的一切,還有編譯器(javac)和工具(如 javadoc 和 jdb)。它能夠創(chuàng)建和編譯程序边琉。

JRE是Java運(yùn)行時(shí)環(huán)境属百,它是運(yùn)行已編譯Java程序所需的所有內(nèi)容的集合,包括Java虛擬機(jī)(JVM)变姨,Java類庫诸老,Java命令和其他的一些基礎(chǔ)構(gòu)件,但是它不能用于創(chuàng)建新程序钳恕。

1.1.2 Java和C++的區(qū)別

相同點(diǎn):

  • 都是面向?qū)ο蟊鸱С址庋b、繼承和多態(tài)

不同點(diǎn):

  • Java沒有指針直接訪問內(nèi)存忧额,程序內(nèi)存更安全
  • Java類是單繼承的厘肮,C++支持多繼承;java接口可以多繼承
  • Java有自動(dòng)內(nèi)存管理機(jī)制睦番,不需要程序員手動(dòng)釋放無用內(nèi)存
  • 在 C 語言中类茂,字符串或字符數(shù)組最后都會(huì)有一個(gè)額外的字符‘\0’來表示結(jié)束。但是托嚣,Java 語言中沒有結(jié)束符這一概念巩检。
1.1.3 什么是Java程序的主類,應(yīng)用程序和小程序的主類有何不同

Java程序的主類是含main方法的類示启。 主方法的修飾符必須是public static void的,但是主類的修飾符不一定是public的。
小程序的主類必須要求是public修飾的球订。

1.1.4 Java應(yīng)用程序與小程序之間的區(qū)別

應(yīng)用程序從主線程啟動(dòng)容燕,也就是從main()方法啟動(dòng);
applet小程序(Java編寫的小應(yīng)用程序,jsp中的java腳本)沒有main()方法,主要是嵌在瀏覽器頁面上運(yùn)行(調(diào)用init()或者run())來啟動(dòng)钦听。

1.1.5 為什么說Java語言“編譯與解釋并存”

編譯型:編譯型語言是指編譯器針對(duì)特定的操作系統(tǒng)將源代碼一次性翻譯成可被該平臺(tái)執(zhí)行的機(jī)器碼畔裕;
解釋型:解釋型語言是指解釋器對(duì)源程序逐行解析成特定平臺(tái)的機(jī)器碼并立即執(zhí)行

Java預(yù)先編譯乖订,生成字節(jié)碼(.class 文件)-> 編譯型扮饶;
字節(jié)碼(.class 文件)需要用Java解釋器來解釋執(zhí)行 -> 解釋型;
Therefore, Java編譯與解釋并存乍构。

1.2 Java語法

1.2.1 Java泛型甜无,類型擦除,常用的通配符

Java泛型:泛型提供了編譯時(shí)類型安全檢測(cè)機(jī)制哥遮,該機(jī)制允許程序員在編譯時(shí)檢測(cè)到非法的類型岂丘。泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)眠饮。

類型擦除:Java的泛型是偽泛型奥帘,因?yàn)镴ava在編譯期間所有的泛型信息都會(huì)被擦掉。

泛型的使用方式:泛型類君仆;泛型接口翩概;泛型方法

泛型類

/**
 * 泛型類
 * 泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)
 */
//此處T可以隨便寫成任意標(biāo)識(shí)返咱,常見的如T,E,K,V等形式的參數(shù)常用于表示泛型
//但是在實(shí)例化泛型類時(shí)钥庇,必須指定T的具體類型
public class GenericClass<T> {

    private T key;

    public GenericClass(T key){
        this.key = key;
        System.out.println(key);
    }

    public T getKey(){
        return key;
    }

    public static void main(String[] args) {
        GenericClass<Integer> genericClassInteger = new GenericClass<>(1234);
    }

}

泛型方法

public class GenericMethod {

    public static <E> void printArray(E[] inputArray){

        for (E element : inputArray){
            System.out.printf("%s",element);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        //可以創(chuàng)建不同類型數(shù)組: Integer, Double 和 Character
        Integer[] intArr = {1,2,3};
        String[] stringArr = {"hello", " ","world"};
        Character[] characterArr = {'c','h','e','e','r'};

        printArray(intArr);
        printArray(stringArr);
        printArray(characterArr);
    }
}

泛型接口

/**
 * 泛型接口
 * @param <T>
 */
public interface Generator<T> {

    public T method();
}

/**
 * 實(shí)現(xiàn)泛型接口,不指定類型
 * @param <T>
 */
public class GeneratorImpl<T> implements Generator<T> {
    @Override
    public T method() {
        return null;
    }
}

/**
 * 實(shí)現(xiàn)泛型接口咖摹,指定類型
 */
public class GeneratorImpl2 implements Generator<String> {

    @Override
    public String method() {
        return "hi~~ cheer";
    }
}

常用的通配符:

  • 评姨?不確定的java類型
  • T (type) 表示具體的一個(gè)java類型
  • K V (key value) 分別表示java鍵值對(duì)中的鍵和值
  • E (element) 表示Element元素
1.2.2 ==和equals的區(qū)別

==:判斷兩個(gè)對(duì)象是不是同一個(gè)對(duì)象,基本數(shù)據(jù)類型比較的是值萤晴, 引用數(shù)據(jù)類型比較的是內(nèi)存地址

equals:比較兩個(gè)對(duì)象是否相等吐句,不能用于比較基本數(shù)據(jù)類型;equals方法存在于Object類之中店读,Object類是所有類的直接或間接父類嗦枢。
類沒有覆蓋equals()方法,等價(jià)通過"=="比較兩個(gè)對(duì)象屯断,默認(rèn)使用Object類的equals()方法文虏。
類覆蓋了equals()方法,某些值或內(nèi)容相等默認(rèn)兩個(gè)對(duì)象相等殖演。例如String之中的equals()方法就是被重寫過的氧秘。

補(bǔ)充關(guān)于String類型的小知識(shí):當(dāng)創(chuàng)建 String 類型的對(duì)象時(shí),虛擬機(jī)會(huì)在常量池中查找有沒有已經(jīng)存在的值和要?jiǎng)?chuàng)建的值相同的對(duì)象趴久,如果有就把它賦給當(dāng)前引用丸相。如果沒有就在常量池中重新創(chuàng)建一個(gè) String 對(duì)象。

1.2.3 hashCode()與equals()

hashCode() 獲取哈希碼(散列碼)彼棍,實(shí)際是一個(gè)int型整數(shù)灭忠。這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置膳算,默認(rèn)對(duì)堆上的對(duì)象產(chǎn)生獨(dú)特的值。散列表中存儲(chǔ)的時(shí)鍵值對(duì)(key-value)更舞, 特點(diǎn)是:能根據(jù)“鍵”快速檢索對(duì)應(yīng)的值畦幢。HashCode方法的主要作用是為了配合基于散列的集合一起正常運(yùn)行,這樣的散列集合包括HashSet缆蝉、HashMap以及HashTable宇葱。

hashCode()存在的意義 提高執(zhí)行速度;當(dāng)你把對(duì)象加入 HashSet 時(shí)刊头,HashSet 會(huì)先計(jì)算對(duì)象的 hashcode 值來判斷對(duì)象加入的位置黍瞧,同時(shí)也會(huì)與其他已經(jīng)加入的對(duì)象的 hashcode 值作比較,如果沒有相符的 hashcode原杂,HashSet 會(huì)假設(shè)對(duì)象沒有重復(fù)出現(xiàn)印颤。但是如果發(fā)現(xiàn)有相同 hashcode 值的對(duì)象,這時(shí)會(huì)調(diào)用 equals()方法來檢查 hashcode 相等的對(duì)象是否真的相同穿肄。如果兩者相同年局,HashSet 就不會(huì)讓其加入操作成功。如果不同的話咸产,就會(huì)重新散列到其他位置矢否。

為什么重寫equals()時(shí)必須重寫hashCode方法
hashCode()和equals()的相關(guān)規(guī)定: 兩對(duì)象相等則hashcode一定相等;兩個(gè)對(duì)象相等脑溢,equals方法會(huì)返回true僵朗;兩對(duì)象hashcode值相等,它們不一定相等

重新equals是希望兩個(gè)對(duì)象在某些值相等的時(shí)候就默認(rèn)相等屑彻,hashCode()的默認(rèn)行為是對(duì)堆上的對(duì)象產(chǎn)生獨(dú)特值验庙。如果沒有重寫 hashCode(),則該 class 的兩個(gè)對(duì)象無論如何都不會(huì)相等(即使這兩個(gè)對(duì)象指向相同的數(shù)據(jù))社牲。

為什么兩個(gè)對(duì)象有相同的hashcode值粪薛,它們也不一定相等
因?yàn)?hashCode() 所使用的雜湊算法也許剛好會(huì)讓多個(gè)對(duì)象傳回相同的雜湊值。越糟糕的雜湊算法越容易碰撞搏恤,但這也與數(shù)據(jù)值域分布的特性有關(guān)(所謂碰撞也就是指的是不同的對(duì)象得到相同的 hashCode汗菜。-- hash碰撞問題

重寫equals和hashCode方法

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * equals() and hashCode(), which are used in various collections
 *
 * Summary:
 * 1. If two objects are equal, they MUST have the same hashcode
 * 2.
 */
public class equalAndHashCode {

    private static class Person{
        private String firstName;
        private String lastName;
        private int ssn;

        public Person(String firstName, String lastName, int ssn) {
            this.firstName = firstName;
            this.lastName = lastName;
            this.ssn = ssn;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public int getSsn() {
            return ssn;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (!(obj instanceof Person)) return false;
            Person p = (Person) obj;
            return this.firstName.equals(p.getFirstName())
                    &&this.lastName.equals(p.getLastName())
                    &&this.ssn == p.getSsn();
        }

        @Override
        public int hashCode() {
            return Objects.hash(firstName,lastName,ssn);
        }
    }

    public static void main(String[] args) {
        Person p1 = new Person("John","Smith",111111);
        Person p2 = new Person("John","Smith",111111);
        Person p3 = new Person("Bob","Smith",111111);

        System.out.println(p1.equals(p2));
        System.out.println(p1.equals(p3));

        Set<Person> set = new HashSet<>();
        set.add(p1);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set.size());
    }

}

1.3 基本數(shù)據(jù)類型

1.3.1 8種基本類型的包裝類和常量池
基本類型占用的字節(jié)數(shù)

實(shí)現(xiàn)常量池的基本類型的包裝類
Java 基本類型的包裝類的大部分都實(shí)現(xiàn)了常量池技術(shù),即 Byte,Short,Integer,Long,Character,Boolean挑社;前面 4 種包裝類默認(rèn)創(chuàng)建了數(shù)值[-128,127] 的相應(yīng)類型的緩存數(shù)據(jù)巡揍,Character創(chuàng)建了數(shù)值在[0,127]范圍的緩存數(shù)據(jù)痛阻,Boolean 直接返回True Or False。如果超出對(duì)應(yīng)范圍仍然會(huì)去創(chuàng)建新的對(duì)象腮敌。-- 為相應(yīng)的包裝類創(chuàng)建對(duì)應(yīng)類型的緩存數(shù)據(jù)
兩種浮點(diǎn)數(shù)類型的包裝類Float和Double沒有實(shí)現(xiàn)常量池技術(shù)阱当。

應(yīng)用場(chǎng)景

  • Integer i1=40俏扩;Java 在編譯的時(shí)候會(huì)直接將代碼封裝成 Integer i1=Integer.valueOf(40);,從而使用常量池中的對(duì)象弊添。
  • Integer i1 = new Integer(40);這種情況下會(huì)創(chuàng)建新的對(duì)象录淡。

代碼示例

public class testConstantPool {

    public static void main(String[] args) {
        //對(duì)Integer線程池技術(shù)理解
       /* Integer i1 = 33;
        Integer i2 = 33;
        System.out.println(i1 == i2); //輸出為true,由于緩沖數(shù)據(jù)池的存在

        Integer i11 = 333;
        Integer i22 = 333;
        System.out.println(i11 == i22); //輸出為false

        Double i3 = 1.2;
        Double i4 = 1.2;
        System.out.println(i3 == i4); //輸出為false, Float Double并沒有實(shí)現(xiàn)常量池技術(shù)*/

        //Integer比較豐富的例子
        Integer i1 = 40;
        Integer i2 = 40;
        Integer i3 = 0;
        Integer i4 = new Integer(40);
        Integer i5 = new Integer(40);
        Integer i6 = new Integer(0);

        System.out.println("i1=i2   " + (i1 == i2)); //true
        System.out.println("i1=i2+i3   " + (i1 == i2 + i3)); //true
        System.out.println("i1=i4   " + (i1 == i4)); //false
        System.out.println("i4=i5   " + (i4 == i5));//false
        /**
         *解釋:
         * 語句 i4 == i5 + i6油坝,因?yàn)?這個(gè)操作符不適用于 Integer 對(duì)象嫉戚,+/-/*等運(yùn)算符都會(huì)將數(shù)據(jù)轉(zhuǎn)化成數(shù)值類型來進(jìn)行操作
         * 首先 i5 和 i6 進(jìn)行自動(dòng)拆箱操作,進(jìn)行數(shù)值相加澈圈,即 i4 == 40彬檀。
         * 然后 Integer 對(duì)象無法與數(shù)值進(jìn)行直接比較,
         * 所以 i4 自動(dòng)拆箱轉(zhuǎn)為 int 值 40瞬女,最終這條語句轉(zhuǎn)為 40 == 40 進(jìn)行數(shù)值比較窍帝。
         */
        System.out.println("i4=i5+i6   " + (i4 == i5 + i6)); //true
        System.out.println("40=i5+i6   " + (40 == i5 + i6)); //true
    }

}

1.4 方法(函數(shù))

1.4.1 為什么Java中只有值傳遞

按值調(diào)用:表示方法接收的是調(diào)用者提供的值
按引用調(diào)用:表示方法接收的是調(diào)用者提供的變量地址。
一個(gè)方法可以改變傳遞引用所對(duì)應(yīng)的原變量的值诽偷,而不能修改傳遞值調(diào)用對(duì)應(yīng)的變量值坤学。

Java程序設(shè)計(jì)的特點(diǎn)
Java 程序設(shè)計(jì)語言總是采用按值調(diào)用。也就是說报慕,方法得到的是所有參數(shù)值的一個(gè)拷貝深浮,也就是說,方法不能修改傳遞給它的任何參數(shù)變量的內(nèi)容卖子。

Java中方法參數(shù)的使用情況

一個(gè)方法不能修改一個(gè)基本數(shù)據(jù)類型的參數(shù)(即數(shù)值型或布爾型)

方法不能改變基本類型的數(shù)值
/**
 * 我們已經(jīng)知道了一個(gè)方法不能修改一個(gè)基本數(shù)據(jù)類型的參數(shù)
 */
public class primaryDataTypePara {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 20;

        swap(num1, num2);

        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
    }

    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;

        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
}

一個(gè)方法可以修改一個(gè)對(duì)象參數(shù)的狀態(tài)

方法可以改變對(duì)象參數(shù)的狀態(tài)
/**
 * 實(shí)現(xiàn)一個(gè)改變對(duì)象參數(shù)狀態(tài)的方法并不是一件難事略号。
 * 理由很簡(jiǎn)單,方法得到的是對(duì)象引用的拷貝洋闽,對(duì)象引用及其他的拷貝同時(shí)引用同一個(gè)對(duì)象玄柠。
 */
public class referencePara {

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3, 4, 5 };
        System.out.println(arr[0]);
        change(arr);
        System.out.println(arr[0]);
    }

    public static void change(int[] array) {
        // 將數(shù)組的第一個(gè)元素變?yōu)?
        array[0] = 0;
    }
}

一個(gè)方法不能讓原本的對(duì)象參數(shù)引用一個(gè)新的對(duì)象

方法不能讓對(duì)象參數(shù)引用新的對(duì)象
/**
 * 方法并沒有改變存儲(chǔ)在變量 s1 和 s2 中的對(duì)象引用。
 * swap 方法的參數(shù) x 和 y 被初始化為兩個(gè)對(duì)象引用的拷貝诫舅,
 * 這個(gè)方法交換的是這兩個(gè)拷貝
 */
public class referenceParaSwap {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Student s1 = new Student("小張");
        Student s2 = new Student("小李");
        referenceParaSwap.swap(s1, s2);
        System.out.println("s1:" + s1.getName());
        System.out.println("s2:" + s2.getName());
    }

    public static void swap(Student x, Student y) {
        Student temp = x;
        x = y;
        y = temp;
        System.out.println("x:" + x.getName());
        System.out.println("y:" + y.getName());
    }


    static class Student{
        private String name;

        public Student(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

1.4.2 重載和重寫方法的區(qū)別

從發(fā)生范圍羽利、參數(shù)列表、返回類型刊懈、異常这弧、訪問修飾符和發(fā)生階段來進(jìn)行說明。

重載重寫區(qū)別點(diǎn)
1.4.3 深拷貝 vs 淺拷貝

淺拷貝: 對(duì)基本數(shù)據(jù)類型進(jìn)行值傳遞虚汛,對(duì)引用數(shù)據(jù)類型進(jìn)行傳遞般的拷貝匾浪,此為淺拷貝。
深拷貝: 對(duì)基本數(shù)據(jù)類型進(jìn)行值傳遞卷哩,對(duì)引用數(shù)據(jù)類型蛋辈,創(chuàng)建一個(gè)新對(duì)象,并復(fù)制其內(nèi)容,為深拷貝

淺拷貝和深拷貝

2. Java面向?qū)ο?/h1>

2.1 類和對(duì)象

2.1.1 面向?qū)ο蠛兔嫦蜻^程的區(qū)別

面向過程: 大多數(shù)面向過程的語言大多數(shù)是直接編譯成機(jī)械碼在電腦上執(zhí)行冷溶,并且其他的一些面向過程的腳本語言的性能不一定比Java好渐白。不需要實(shí)例化對(duì)象。所以當(dāng)性能是最重要的考量因素的時(shí)候逞频,比如單片機(jī)纯衍、嵌入式開發(fā)、Linux/Unix 等一般采用面向過程開發(fā)苗胀。

面向?qū)ο? 面向?qū)ο笠拙S護(hù)襟诸、易復(fù)用、易擴(kuò)展柒巫。 因?yàn)槊嫦驅(qū)ο笥蟹庋b励堡、繼承、多態(tài)性的特性堡掏,所以可以設(shè)計(jì)出低耦合的系統(tǒng)祭饭,使系統(tǒng)更加靈活岂却、更加易于維護(hù)狰挡。Java 性能差的主要原因并不是因?yàn)樗敲嫦驅(qū)ο笳Z言吴趴,而是 Java 是半編譯語言,最終的執(zhí)行代碼并不是可以直接被 CPU 執(zhí)行的二進(jìn)制機(jī)械碼亭畜。

2.1.2 在Java定義一個(gè)不做事并且沒有參數(shù)的構(gòu)造函數(shù)的作用

為了子類好:Java 程序在執(zhí)行子類的構(gòu)造方法之前扮休,如果沒有用 super()來調(diào)用父類特定的構(gòu)造方法,則會(huì)調(diào)用父類中“沒有參數(shù)的構(gòu)造方法”拴鸵。因此玷坠,如果父類中只定義了有參數(shù)的構(gòu)造方法,而在子類的構(gòu)造方法中又沒有用 super()來調(diào)用父類中特定的構(gòu)造方法劲藐,則編譯時(shí)將發(fā)生錯(cuò)誤八堡,因?yàn)?Java 程序在父類中找不到?jīng)]有參數(shù)的構(gòu)造方法可供執(zhí)行。

子類實(shí)例化時(shí)聘芜,默認(rèn)調(diào)用父類的無參構(gòu)造方法(不管子類的構(gòu)造器有沒有參數(shù)兄渺,因?yàn)樽宇惱^承的是父類的屬性和方法,只調(diào)用父類的無參構(gòu)造器就可以繼承父類的屬性和方法汰现,因此不會(huì)調(diào)用父類的有參構(gòu)造器)挂谍,再調(diào)用子類的有參/無參構(gòu)造器。

2.1.3 創(chuàng)建對(duì)象所用的運(yùn)算符瞎饲;對(duì)象實(shí)體和對(duì)象引用的不同點(diǎn)

創(chuàng)建對(duì)象所用的運(yùn)算符: new
區(qū)別點(diǎn):對(duì)象實(shí)例存在堆內(nèi)存中口叙,對(duì)象引用存在棧內(nèi)存中;一個(gè)對(duì)象引用可以指向0個(gè)或1個(gè)對(duì)象嗅战,一個(gè)對(duì)象可以有n個(gè)引用指向它庐扫。
堆和棧的區(qū)別:
內(nèi)存大小:堆非常大;棧很小
工作效率:堆相對(duì)比較慢形庭,棧就會(huì)快一些

2.1.4 調(diào)用子類構(gòu)造方法之前會(huì)先調(diào)用父類無參的構(gòu)造方法,目的厌漂?

因?yàn)樽宇惱^承的是父類的屬性和方法萨醒,只調(diào)用父類的無參構(gòu)造器就可以繼承父類的屬性和方法,因此調(diào)用父類的無參構(gòu)造器是為了幫助子類做初始化工作苇倡。

2.2 面向?qū)ο蟮娜筇卣?/h3>

2.2.1 封裝

封裝是指把一個(gè)對(duì)象的狀態(tài)信息(也就是屬性)隱藏在對(duì)象內(nèi)部富纸,不允許外部對(duì)象直接訪問對(duì)象的內(nèi)部信息。但是可以提供一些可以被外界訪問的方法來操作屬性旨椒。

2.2.2 繼承

繼承是使用已存在的類的定義作為基礎(chǔ)建立新類的技術(shù)晓褪,新類的定義可以增加新的數(shù)據(jù)或新的功能,也可以用父類的功能综慎,但不能選擇性地繼承父類涣仿。通過使用繼承,可以快速地創(chuàng)建新的類示惊,可以提高代碼的重用好港,程序的可維護(hù)性,節(jié)省大量創(chuàng)建新類的時(shí)間 米罚,提高我們的開發(fā)效率钧汹。

  • 子類擁有父類對(duì)象所有的屬性和方法(包括私有屬性和私有方法),但是父類中的私有屬性和方法子類是無法訪問录择,只是擁有拔莱。
  • 子類可以擁有自己屬性和方法,即子類可以對(duì)父類進(jìn)行擴(kuò)展隘竭。
  • 子類可以用自己的方式實(shí)現(xiàn)父類的方法塘秦。
2.2.3 多態(tài)

表示一個(gè)對(duì)象具有多種狀態(tài)。具體表現(xiàn)為父類的引用指向子類的實(shí)例货裹。

  • 對(duì)象類型和引用類型之間具有繼承(類)/實(shí)現(xiàn)(接口)的關(guān)系嗤形;
  • 對(duì)象類型不可變,引用類型可變
  • 方法具有多態(tài)性弧圆,屬性不具有多態(tài)性
  • 引用類型變量發(fā)出的方法調(diào)用的到底是哪個(gè)類中的方法赋兵,必須在程序運(yùn)行期間才能確定
  • 多態(tài)不能調(diào)用“只在子類存在但在父類不存在”的方法
  • 如果子類重寫了父類的方法,真正執(zhí)行的是子類覆蓋的方法搔预,如果子類沒有覆蓋父類的方法霹期,執(zhí)行的是父類的方法

2.3 修飾符

2.3.1 常見關(guān)鍵字總結(jié): static, final, this, super

final關(guān)鍵字(不可修改;修飾類拯田、方法和變量)

final關(guān)鍵字修飾的特點(diǎn):

  • final修飾的類不能被繼承历造,final類中的所有成員方法都會(huì)被隱式的指定為final方法
  • final修飾的方法不能被重寫
  • final修飾的變量是常量,如果是基本數(shù)據(jù)類型的變量,則其數(shù)值一旦在初始化之后便不能更改吭产;如果是引用類型的變量侣监,則在對(duì)其初始化之后便不能讓其指向另一個(gè)對(duì)象。

使用final方法的原因:

  • 把方法鎖定臣淤,以防任何繼承類修改它的含義
  • 效率橄霉,在早期的Java實(shí)現(xiàn)版本中,會(huì)將final方法轉(zhuǎn)為內(nèi)嵌調(diào)用邑蒋。類中所有的private方法都隱式地指定為final姓蜂。

static關(guān)鍵字

static關(guān)鍵字使用場(chǎng)景

  • 修飾成員變量和成員方法
    被 static 修飾的成員屬于類,不屬于單個(gè)這個(gè)類的某個(gè)對(duì)象医吊,被類中所有對(duì)象共享(不屬于單個(gè)實(shí)例)钱慢,可以并且建議通過類名調(diào)用。被static 聲明的成員變量屬于靜態(tài)成員變量卿堂,調(diào)用格式:類名.靜態(tài)變量名 類名.靜態(tài)方法名()束莫。靜態(tài)變量 存放在 Java 內(nèi)存區(qū)域的方法區(qū)。
    方法區(qū)與 Java 堆一樣御吞,是各個(gè)線程共享的內(nèi)存區(qū)域麦箍,它用于存儲(chǔ)已被虛擬機(jī)加載的類信息、常量陶珠、靜態(tài)變量挟裂、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分揍诽,但是它卻有一個(gè)別名叫做 Non-Heap(非堆)诀蓉,目的應(yīng)該是與 Java 堆區(qū)分開來。
/**
* static修飾的成員屬于類的例子
*/
public class StaticBean {
    private String name;
    //靜態(tài)變量
    static int age;

    public StaticBean(String name) {
        this.name = name;
    }
    //靜態(tài)方法
    static void SayHello() {
        System.out.println("Hello i am java");
    }
    @Override
    public String toString() {
        return "StaticBean{"+
                "name=" + name + ",age=" + age +
                "}";
    }
}

public class StaticDemo {

    public static void main(String[] args) {
        StaticBean staticBean = new StaticBean("1");
        StaticBean staticBean2 = new StaticBean("2");
        StaticBean staticBean3 = new StaticBean("3");
        StaticBean staticBean4 = new StaticBean("4");
        //static變量是屬于整個(gè)類的暑脆,所以賦值就使得該類的所有實(shí)例的age有了相應(yīng)的改變
        StaticBean.age = 33;
        System.out.println(staticBean + " " + staticBean2 + " " + staticBean3 + " " + staticBean4);
        //StaticBean{name=1,age=33} StaticBean{name=2,age=33} StaticBean{name=3,age=33} StaticBean{name=4,age=33}
        StaticBean.SayHello();//Hello i am java
    }

}
  • 靜態(tài)代碼塊
    靜態(tài)代碼塊: 靜態(tài)代碼塊定義在類中方法外, 靜態(tài)代碼塊在非靜態(tài)代碼塊之前執(zhí)行(靜態(tài)代碼塊—>非靜態(tài)代碼塊—>構(gòu)造方法)渠啤。 該類不管創(chuàng)建多少對(duì)象,靜態(tài)代碼塊只執(zhí)行一次.
    一個(gè)類中的靜態(tài)代碼塊可以有多個(gè)添吗,位置可以隨便放沥曹,它不在任何的方法體內(nèi),JVM加載類時(shí)會(huì)執(zhí)行這些靜態(tài)的代碼塊碟联,如果靜態(tài)代碼塊有多個(gè)妓美,JVM將按照它們?cè)陬愔谐霈F(xiàn)的先后順序依次執(zhí)行它們,每個(gè)代碼塊只會(huì)被執(zhí)行一次鲤孵。
/**
 * static{}靜態(tài)代碼塊與{}非靜態(tài)代碼塊的執(zhí)行順序
 */
public class CodeBlock {

    public CodeBlock(){
        System.out.println("默認(rèn)構(gòu)造方法壶栋!--");
    }

    /**
     * 每次實(shí)例化都會(huì)執(zhí)行
     */
    //非靜態(tài)代碼塊
    {
        System.out.println("非靜態(tài)代碼塊");
    }

    /**
     * 該類無論創(chuàng)建多少對(duì)象,靜態(tài)代碼塊只執(zhí)行一次
     */
    //靜態(tài)代碼塊
    static {
        System.out.print("靜態(tài)代碼塊普监!--");
    }

    private static void test() {
        System.out.print("靜態(tài)方法中的內(nèi)容! --");
        {
            System.out.print("靜態(tài)方法中的代碼塊贵试!--");
        }
        System.out.println();
    }

    public static void main(String[] args) {

        CodeBlock.test();//靜態(tài)代碼塊琉兜!--靜態(tài)方法中的內(nèi)容! --靜態(tài)方法中的代碼塊!--
        CodeBlock test = new CodeBlock();

    }
}
  • 靜態(tài)內(nèi)部類(static修飾類的花只能修飾內(nèi)部類)
    靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間存在一個(gè)最大的區(qū)別: 非靜態(tài)內(nèi)部類在編譯完成之后會(huì)隱含地保存著一個(gè)引用毙玻,該引用是指向創(chuàng)建它的外圍類豌蟋,但是靜態(tài)內(nèi)部類卻沒有。沒有這個(gè)引用就意味著:1. 它的創(chuàng)建是不需要依賴外圍類的創(chuàng)建淆珊。2. 它不能使用任何外圍類的非static成員變量和方法夺饲。
public class Super {

    private int number;

    void showNumber(){
        System.out.println(this);
        System.out.println("number = " + number);
    }

    static void showNum(){
        System.out.println(1111);
    }


    /**
     * 測(cè)試靜態(tài)內(nèi)部類,靜態(tài)內(nèi)部類不可以引用外部的非
     */
    static class Test{

        void outerMethod(){
            showNum();
        }
    }

    /**
     * 測(cè)試非靜態(tài)內(nèi)部類
     */
    public class Test2{

        void outerMethod(){
            showNumber();
        }
    }

    static class Sub extends Super{
        /**
         * 繼承就意味著子類擁有父類所有屬性和方法(構(gòu)造方法除外)施符。
         * static方法同樣能被繼承,
         * 只是在某些情況下(比如類向上轉(zhuǎn)型時(shí))調(diào)用時(shí)與非static方法出現(xiàn)差異擂找。
         */
        void bar(){
            showNumber();
            super.number=10;
            super.showNumber();
            System.out.println(this);
            System.out.println(super.number);
        }

    }

    public static void main(String[] args) {
        Sub sub = new Sub();
        Sub sub1 = new Sub();

        ((Super)sub).showNumber();
        sub.bar();
        sub1.bar();

        Super super1 = new Super();
        super1.showNumber();

        /**
         * 測(cè)試非靜態(tài)內(nèi)部類
         */
        Test2 test = new Super().new Test2();
        test.outerMethod();

        /**
         * 測(cè)試靜態(tài)內(nèi)部類
         */
        Test test1 = new Super.Test();
        test1.outerMethod();
    }
}
  • 靜態(tài)導(dǎo)包(用來導(dǎo)入類中的靜態(tài)資源戳吝,1.5之后的新特性)
    import static 這兩個(gè)關(guān)鍵字連用可以指定導(dǎo)入某個(gè)類中的指定靜態(tài)資源,并且不需要使用類名調(diào)用類中靜態(tài)成員贯涎,可以直接使用類中靜態(tài)成員變量和成員方法听哭。
import static java.lang.Math.*;

public class staticImportPackage {
    public static void main(String[] args) {
        System.out.println(max(1,4));
    }
}

static method / non-static method

  • 在外部調(diào)用靜態(tài)方法時(shí),可以使用”類名.方法名”的方式塘雳,也可以使用”對(duì)象名.方法名”的方式陆盘。而實(shí)例方法只有后面這種方式。也就是說败明,調(diào)用靜態(tài)方法可以無需創(chuàng)建對(duì)象隘马。
  • 靜態(tài)方法在訪問本類的成員時(shí),只允許訪問靜態(tài)成員(即靜態(tài)成員變量和靜態(tài)方法)妻顶,而不允許訪問實(shí)例成員變量和實(shí)例方法酸员;實(shí)例方法則無此限制
  • 靜態(tài)方法屬于類本身,非靜態(tài)方法屬于從該類生成的每個(gè)對(duì)象讳嘱。 如果您的方法執(zhí)行的操作不依賴于其類的各個(gè)變量和方法幔嗦,請(qǐng)將其設(shè)置為靜態(tài)(這將使程序的占用空間更小)沥潭。 否則邀泉,它應(yīng)該是非靜態(tài)的。

靜態(tài)代碼塊與非靜態(tài)代碼塊

  • 相同點(diǎn): 都是在JVM加載類時(shí)且在構(gòu)造方法執(zhí)行之前執(zhí)行钝鸽,在類中都可以定義多個(gè)汇恤,定義多個(gè)時(shí)按定義的順序執(zhí)行,一般在代碼塊中對(duì)一些static變量進(jìn)行賦值寞埠。
  • 不同點(diǎn): 靜態(tài)代碼塊在非靜態(tài)代碼塊之前執(zhí)行(靜態(tài)代碼塊—非靜態(tài)代碼塊—構(gòu)造方法)屁置。靜態(tài)代碼塊只在執(zhí)行一次,之后不再執(zhí)行仁连,而非靜態(tài)代碼塊在每new一次就執(zhí)行一次蓝角。 非靜態(tài)代碼塊可在普通方法中定義(不過作用不大)阱穗;而靜態(tài)代碼塊不行
  • 非靜態(tài)代碼塊與構(gòu)造函數(shù)的區(qū)別: 非靜態(tài)代碼塊是給所有對(duì)象進(jìn)行統(tǒng)一初始化,而構(gòu)造函數(shù)是給對(duì)應(yīng)的對(duì)象初始化使鹅,因?yàn)闃?gòu)造函數(shù)是可以多個(gè)的揪阶,運(yùn)行哪個(gè)構(gòu)造函數(shù)就會(huì)建立什么樣的對(duì)象,但無論建立哪個(gè)對(duì)象患朱,都會(huì)先執(zhí)行相同的構(gòu)造代碼塊鲁僚。也就是說,非靜態(tài)代碼塊中定義的是不同對(duì)象共性的初始化內(nèi)容裁厅。

this和super關(guān)鍵字

this關(guān)鍵字

  • this關(guān)鍵字用于引用類的當(dāng)前實(shí)例冰沙。可以訪問當(dāng)前實(shí)例的變量和方法执虹。

super關(guān)鍵字

  • super關(guān)鍵字用于從子類訪問父類的變量和方法拓挥。

使用this和super要注意的問題

  • 在構(gòu)造器中使用 super() 調(diào)用父類中的其他構(gòu)造方法時(shí),該語句必須處于構(gòu)造器的首行袋励,否則編譯器會(huì)報(bào)錯(cuò)侥啤。另外,this 調(diào)用本類中的其他構(gòu)造方法時(shí)茬故,也要放在首行盖灸。
  • this、super不能用在static方法中磺芭。(this和super是屬于對(duì)象范疇的東西赁炎,而靜態(tài)方法是屬于類范疇的東西。)

2.4 接口和抽象類

2.4.1 接口和抽象類的區(qū)別
  • 接口的方法默認(rèn)是 public徘跪,所有方法在接口中不能有實(shí)現(xiàn)(Java 8 開始接口方法可以有默認(rèn)實(shí)現(xiàn))甘邀,而抽象類可以有非抽象的方法。
  • 接口中除了 static垮庐、final 變量松邪,不能有其他變量,而抽象類中則不一定哨查。
  • 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口逗抑,但只能實(shí)現(xiàn)一個(gè)抽象類。接口自己本身可以通過 extends 關(guān)鍵字?jǐn)U展多個(gè)接口寒亥。
  • 接口方法默認(rèn)修飾符是 public邮府,抽象方法可以有 public、protected 和 default 這些修飾符(抽象方法就是為了被重寫所以不能使用 private 關(guān)鍵字修飾8绒取)褂傀。
  • 從設(shè)計(jì)層面來說,抽象是對(duì)類的抽象加勤,是一種模板設(shè)計(jì)仙辟,而接口是對(duì)行為的抽象同波,是一種行為的規(guī)范。
  • 總結(jié)一下 jdk7~jdk9 Java 中接口概念的變化: 在 jdk 7 或更早版本中叠国,接口里面只能有常量變量和抽象方法未檩。這些接口方法必須由選擇實(shí)現(xiàn)接口的類實(shí)現(xiàn); jdk8 的時(shí)候接口可以有默認(rèn)方法和靜態(tài)方法功能粟焊; Jdk 9 在接口中引入了私有方法和私有靜態(tài)方法.
/**
 * java8的時(shí)候接口有默認(rèn)方法和靜態(tài)方法功能
 */
public interface Test {
    
    public void generalInterfaceMethod();

    default void defaultMethod(){
      System.out.println("test default method");
    }

    public static void test(){
        System.out.println("hahahahha");
    }

    public static void main(String[] args) {
        Test.test();
    }

}

2.5 其它重要的知識(shí)點(diǎn)

2.5.1 String StringBuffer和StringBuilder的區(qū)別冤狡, String為什么不可變

String StringBuffer和StringBuilder

  • String 類中使用 final 關(guān)鍵字修飾字符數(shù)組來保存字符串,private final char value[]项棠,所以 String 對(duì)象是不可變的悲雳。
  • 而 StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符數(shù)組保存字符串char[]value 但是沒有用 final 關(guān)鍵字修飾香追,所以這兩種對(duì)象都是可變的怜奖。

線程安全性

  • String 中的對(duì)象是不可變的,也就可以理解為常量翅阵,線程安全。AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類迁央,定義了一些字符串的基本操作掷匠,如 expandCapacity、append岖圈、insert讹语、indexOf 等公共方法。StringBuffer 對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖蜂科,所以是線程安全的顽决。StringBuilder 并沒有對(duì)方法進(jìn)行加同步鎖,所以是非線程安全的导匣。

性能

  • 每次對(duì) String 類型進(jìn)行改變的時(shí)候才菠,都會(huì)生成一個(gè)新的 String 對(duì)象,然后將指針指向新的 String 對(duì)象贡定。StringBuffer 每次都會(huì)對(duì) StringBuffer 對(duì)象本身進(jìn)行操作赋访,而不是生成新的對(duì)象并改變對(duì)象引用。相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升缓待,但卻要冒多線程不安全的風(fēng)險(xiǎn)

對(duì)三者使用的總結(jié)

  • 操作少量的數(shù)據(jù): 適用 String
  • 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用 StringBuilder
  • 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用 StringBuffer
2.5.2 Object類的常見方法總結(jié)

Object 類是一個(gè)特殊的類蚓耽,是所有類的父類。它主要提供了以下 11 個(gè)方法

public final native Class<?> getClass()//native方法旋炒,用于返回當(dāng)前運(yùn)行時(shí)對(duì)象的Class對(duì)象步悠,使用了final關(guān)鍵字修飾,故不允許子類重寫瘫镇。

public native int hashCode() //native方法鼎兽,用于返回對(duì)象的哈希碼答姥,主要使用在哈希表中,比如JDK中的HashMap接奈。
public boolean equals(Object obj)//用于比較2個(gè)對(duì)象的內(nèi)存地址是否相等踢涌,String類對(duì)該方法進(jìn)行了重寫用戶比較字符串的值是否相等。

protected native Object clone() throws CloneNotSupportedException//naitive方法序宦,用于創(chuàng)建并返回當(dāng)前對(duì)象的一份拷貝睁壁。一般情況下,對(duì)于任何對(duì)象 x互捌,表達(dá)式 x.clone() != x 為true潘明,x.clone().getClass() == x.getClass() 為true。Object本身沒有實(shí)現(xiàn)Cloneable接口秕噪,所以不重寫clone方法并且進(jìn)行調(diào)用的話會(huì)發(fā)生CloneNotSupportedException異常钳降。

public String toString()//返回類的名字@實(shí)例的哈希碼的16進(jìn)制的字符串。建議Object所有的子類都重寫這個(gè)方法腌巾。

public final native void notify()//native方法遂填,并且不能重寫。喚醒一個(gè)在此對(duì)象監(jiān)視器上等待的線程(監(jiān)視器相當(dāng)于就是鎖的概念)澈蝙。如果有多個(gè)線程在等待只會(huì)任意喚醒一個(gè)吓坚。

public final native void notifyAll()//native方法,并且不能重寫灯荧。跟notify一樣礁击,唯一的區(qū)別就是會(huì)喚醒在此對(duì)象監(jiān)視器上等待的所有線程,而不是一個(gè)線程逗载。

public final native void wait(long timeout) throws InterruptedException//native方法哆窿,并且不能重寫。暫停線程的執(zhí)行厉斟。注意:sleep方法沒有釋放鎖挚躯,而wait方法釋放了鎖 。timeout是等待時(shí)間捏膨。

public final void wait(long timeout, int nanos) throws InterruptedException//多了nanos參數(shù)秧均,這個(gè)參數(shù)表示額外時(shí)間(以毫微秒為單位号涯,范圍是 0-999999)目胡。 所以超時(shí)的時(shí)間還需要加上nanos毫秒誉己。

public final void wait() throws InterruptedException//跟之前的2個(gè)wait方法一樣,只不過該方法一直等待域蜗,沒有超時(shí)時(shí)間這個(gè)概念

protected void finalize() throws Throwable { }//實(shí)例被垃圾回收器回收的時(shí)候觸發(fā)的操作
2.5.3 Java序列化如果有些字段不想進(jìn)行序列化巨双,怎么辦

使用transient關(guān)鍵字噪猾,阻止實(shí)例中那些用此關(guān)鍵字修飾的的變量序列化;當(dāng)對(duì)象被反序列化時(shí)筑累,被 transient 修飾的變量值不會(huì)被持久化和恢復(fù)袱蜡。transient 只能修飾變量,不能修飾類和方法慢宗。
序列化和反序列化: Java 序列化是指把 Java 對(duì)象轉(zhuǎn)換為字節(jié)序列的過程便于保存在內(nèi)存坪蚁、文件、數(shù)據(jù)庫中镜沽,ObjectOutputStream類的 writeObject() 方法可以實(shí)現(xiàn)序列化敏晤。

Java 反序列化是指把字節(jié)序列恢復(fù)為 Java 對(duì)象的過程,ObjectInputStream 類的 readObject() 方法用于反序列化缅茉。

2.5.4 獲取用鍵盤輸入常用的兩種方法
  • 通過Scanner
  • 通過BufferReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class KeyboardInput {
    public static void main(String[] args) throws IOException {
        /*Scanner input = new Scanner(System.in);
        String s = input.nextLine();
        System.out.println(s);
        input.close();*/

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        String s = input.readLine();
        System.out.println(s);
    }
}

3. Java核心技術(shù)

3.1 集合

3.1.1 Collections工具類和Arrays工具類常見方法總結(jié)

Collections工具類和Arrays工具類都是對(duì)原本數(shù)組直接進(jìn)行操作

Collections

  • 排序操作
void reverse(List list)://反轉(zhuǎn)
void rotate(List list, int distance)//旋轉(zhuǎn)嘴脾。當(dāng)distance為正數(shù)時(shí),將list后distance個(gè)元素整體移到前面蔬墩。當(dāng)distance為負(fù)數(shù)時(shí)译打,將 list的前distance個(gè)元素整體移到后面。
void sort(List list) //按自然排序的升序排序
void shuffle(List list) //隨機(jī)排序
void swap(List list, int i , int j) //交換兩個(gè)索引位置的元素
//定制排序的用法
        Collections.sort(arrayList, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });

具體的實(shí)例:

        /**
         * 排序的常用方法
         */
/*        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(-1);
        arrayList.add(3);
        arrayList.add(3);
        arrayList.add(-5);
        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(-9);
        arrayList.add(-7);
        System.out.println("原始數(shù)組:");
        System.out.println(arrayList);

        // void reverse(List list):反轉(zhuǎn)
        Collections.reverse(arrayList);
        System.out.println("Collections.reverse(arrayList):");
        System.out.println(arrayList);

        //void rotate(List list, int distance)//旋轉(zhuǎn)拇颅。當(dāng)distance為正數(shù)時(shí)扶平,
        //將list后distance個(gè)元素整體移到前面。當(dāng)distance為負(fù)數(shù)時(shí)蔬蕊,將 list的前distance個(gè)元素整體移到后面。
        Collections.rotate(arrayList,4);
        System.out.println("Collections.rotate(arrayList, 4):");
        System.out.println(arrayList);

        //void sort(List list),按自然排序的升序排序
        Collections.sort(arrayList);
        System.out.println("Collections.sort(arrayList):");
        System.out.println(arrayList);

        //void shuffle(List list),隨機(jī)排序
        Collections.shuffle(arrayList);
        System.out.println("Collections.shuffle(arrayList):");
        System.out.println(arrayList);

        //void swap(List list, int i , int j),交換兩個(gè)索引位置的元素
        Collections.swap(arrayList, 2, 5);
        System.out.println("Collections.swap(arrayList, 2, 5):");
        System.out.println(arrayList);

        //定制排序的用法
        Collections.sort(arrayList, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });
        System.out.println("定制排序后: ");
        System.out.println(arrayList);*/
  • 查找/替換操作
int max(Collection coll)//根據(jù)元素的自然順序哥谷,返回最大的元素岸夯。 類比int min(Collection coll)
boolean replaceAll(List list, Object oldVal, Object newVal) //用新元素替換舊元素
int indexOfSubList(List list, List target) //統(tǒng)計(jì)target在list中第一次出現(xiàn)的索引,找不到則返回-1们妥,類比int lastIndexOfSubList(List source, list target).
Collections.binarySearch(arrayList, 7) //

具體實(shí)例:

/**
         * 查找猜扮,替換操作
         */
/*        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(-1);
        arrayList.add(3);
        arrayList.add(3);
        arrayList.add(-5);
        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(-9);
        arrayList.add(-7);
        ArrayList<Integer> arrayList2 = new ArrayList<Integer>();
        arrayList2.add(-3);
        arrayList2.add(-5);
        arrayList2.add(7);
        System.out.println("原始數(shù)組:");
        System.out.println(arrayList);

        //int max(Collection coll)//根據(jù)元素的自然順序,返回最大的元素监婶。 類比int min(Collection coll)
        System.out.println("Collections.max(arrayList):");
        System.out.println(Collections.max(arrayList));

        System.out.println("Collections.min(arrayList):");
        System.out.println(Collections.min(arrayList));

        //collections是對(duì)原本的數(shù)組直接進(jìn)行操作
        //boolean replaceAll(List list, Object oldVal, Object newVal), 用新元素替換舊元素
        System.out.println("Collections.replaceAll(arrayList, 3, -3):");
        Collections.replaceAll(arrayList, 3, -3);
        System.out.println(arrayList);

        //int indexOfSubList(List list, List target)//統(tǒng)計(jì)target在list中第一次出現(xiàn)的索引旅赢,
        //找不到則返回-1,類比int lastIndexOfSubList(List source, list target).
        System.out.println("Collections.indexOfSubList(arrayList, arrayList2):");
        System.out.println(Collections.indexOfSubList(arrayList, arrayList2));

        System.out.println("Collections.binarySearch(arrayList, 7):");
        // 對(duì)List進(jìn)行二分查找惑惶,返回索引煮盼,List必須是有序的
        Collections.sort(arrayList);
        System.out.println(Collections.binarySearch(arrayList, 7));*/
  • 同步控制
    • 提供了多個(gè)synchronizedXXX()方法
      Collections提供了多個(gè)synchronizedXxx()方法·,該方法可以將指定集合包裝成線程同步的集合带污,從而解決多線程并發(fā)訪問集合時(shí)的線程安全問題僵控。
      我們知道 HashSet,TreeSet鱼冀,ArrayList,LinkedList,HashMap,TreeMap 都是線程不安全的报破。Collections提供了多個(gè)靜態(tài)方法可以把他們包裝成線程同步的集合悠就。
      最好不要用下面這些方法,效率非常低充易,需要線程安全的集合類型時(shí)請(qǐng)考慮使用 JUC 包下的并發(fā)集合梗脾。
    • 設(shè)置不可變集合
      emptyXxx(): 返回一個(gè)空的、不可變的集合對(duì)象盹靴,此處的集合可以是:List炸茧,Set,Map鹉究。
      singletonXxx(): 返回一個(gè)只包含指定對(duì)象(只有一個(gè)或一個(gè)元素)的不可變的集合對(duì)象宇立,此處的集合可以是:List,Set自赔,Map妈嘹。
      unmodifiableXxx(): 返回指定集合對(duì)象的不可變視圖,此處的集合可以是:List绍妨,Set润脸,Map。
      上面三類方法的參數(shù)是原有的集合對(duì)象他去,返回值是該集合的”只讀“版本毙驯。
        /**
         * collections設(shè)置不可變集合
         */
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(-1);
        arrayList.add(3);
        arrayList.add(3);
        arrayList.add(-5);
        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(-9);
        arrayList.add(-7);
        HashSet<Integer> integers1 = new HashSet<>();
        integers1.add(1);
        integers1.add(3);
        integers1.add(2);
        Map scores = new HashMap();
        scores.put("語文" , 80);
        scores.put("Java" , 82);

        //Collections.emptyXXX();創(chuàng)建一個(gè)空的、不可改變的XXX對(duì)象
        List<Object> list = Collections.emptyList();
        System.out.println(list);//[]
        Set<Object> objects = Collections.emptySet();
        System.out.println(objects);//[]
        Map<Object, Object> objectObjectMap = Collections.emptyMap();
        System.out.println(objectObjectMap);//{}

        //!!!返回的內(nèi)容只包含一個(gè)指定對(duì)象
        //singletonXxx(): 返回一個(gè)只包含指定對(duì)象(只有一個(gè)或一個(gè)元素)的不可變的集合對(duì)象灾测,
        //此處的集合可以是:List爆价,Set,Map媳搪。
        List<Map<String, String>> mapList = Collections.singletonList(scores);
        System.out.println(mapList);
        List<ArrayList<Integer>> arrayLists = Collections.singletonList(arrayList);
        System.out.println(arrayLists);//[[-1, 3, 3, -5, 7, 4, -9, -7]]
        //創(chuàng)建一個(gè)只有一個(gè)元素铭段,且不可改變的Set對(duì)象
        Set<ArrayList<Integer>> singleton = Collections.singleton(arrayList);
        System.out.println(singleton);//[[-1, 3, 3, -5, 7, 4, -9, -7]]
        Map<String, String> nihao = Collections.singletonMap("1", "nihao");
        System.out.println(nihao);//{1=nihao}

        //unmodifiableXXX(); 創(chuàng)建普通XXX對(duì)象對(duì)應(yīng)的不可變版本
        List<Integer> integers = Collections.unmodifiableList(arrayList);
        System.out.println(integers);//[-1, 3, 3, -5, 7, 4, -9, -7]
        Set<Integer> integers2 = Collections.unmodifiableSet(integers1);
        System.out.println(integers2);//[1, 2, 3]
        Map<Object, Object> objectObjectMap2 = Collections.unmodifiableMap(scores);
        System.out.println(objectObjectMap2);//{Java=82, 語文=80}

        //添加會(huì)出現(xiàn)異常
        /*list.add(1);
        arrayLists.add(arrayList);
        integers.add(1);*/

Arrays

  • 排序: sort();查找: binarySearch()秦爆;比較: equals()序愚;填充: fill();轉(zhuǎn)列表: asList()等限;轉(zhuǎn)字符串: toString()爸吮;復(fù)制: copyOf()

具體實(shí)例

import java.util.Arrays;
import java.util.List;

/**
 * arrays類的常見方法
 */
public class arraysMethods {

    public static void main(String[] args) {
        //1. 排序: sort()
        // *************排序 sort****************
        int a[] = { 1, 3, 2, 7, 6, 5, 4, 9 };
        // sort(int[] a)方法按照數(shù)字順序排列指定的數(shù)組。
        Arrays.sort(a);
        System.out.println("Arrays.sort(a):");
        for (int i : a) {
            System.out.print(i);
        }
        // 換行
        System.out.println();

        // sort(int[] a,int fromIndex,int toIndex)按升序排列數(shù)組的指定范圍
        int b[] = { 1, 3, 2, 7, 6, 5, 4, 9 };
        Arrays.sort(b, 2, 6);
        System.out.println("Arrays.sort(b, 2, 6):");
        for (int i : b) {
            System.out.print(i);
        }
        // 換行
        System.out.println();

        int c[] = { 1, 3, 2, 7, 6, 5, 4, 9 };
        // parallelSort(int[] a) 按照數(shù)字順序排列指定的數(shù)組(并行的)望门。同sort方法一樣也有按范圍的排序
        Arrays.parallelSort(c);
        System.out.println("Arrays.parallelSort(c):");
        for (int i : c) {
            System.out.print(i);
        }
        // 換行
        System.out.println();

        // parallelSort給字符數(shù)組排序形娇,sort也可以
        char d[] = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
        Arrays.parallelSort(d);
        System.out.println("Arrays.parallelSort(d):");
        for (char d2 : d) {
            System.out.print(d2);
        }
        // 換行
        System.out.println();

        //Collections可以對(duì)字符串進(jìn)行排序
        String[] strs = { "abcdehg", "abcdefg", "abcdeag" };
        Arrays.sort(strs);
        System.out.println(Arrays.toString(strs));//[abcdeag, abcdefg, abcdehg]

        /**
         * 2.查找 binarySearch
         */
        // *************查找 binarySearch()****************
        char[] e = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
        // 排序后再進(jìn)行二分查找,否則找不到
        Arrays.sort(e);
        System.out.println("Arrays.sort(e)" + Arrays.toString(e));
        System.out.println("Arrays.binarySearch(e, 'c'):");
        int s = Arrays.binarySearch(e, 'c');
        System.out.println("字符c在數(shù)組的位置:" + s);

        /**
         * 3. 比較: equals()
         */
        // *************比較 equals****************
        // *************比較 equals****************
        char[] e1 = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
        char[] f = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
        /*
         * 元素?cái)?shù)量相同筹误,并且相同位置的元素相同埂软。 另外,如果兩個(gè)數(shù)組引用都是null,則它們被認(rèn)為是相等的 勘畔。
         */
        // 輸出true
        System.out.println("Arrays.equals(e, f):" + Arrays.equals(e1, f));

        /**
         * 4.填充: fill(), 批量進(jìn)行初始化
         */
        // *************填充fill(批量初始化)****************
        int[] g = { 1, 2, 3, 3, 3, 3, 6, 6, 6 };
        // 數(shù)組中所有元素重新分配值
        Arrays.fill(g, 3);
        System.out.println("Arrays.fill(g, 3):");
        // 輸出結(jié)果:333333333
        for (int i : g) {
            System.out.print(i);
        }
        // 換行
        System.out.println();

        int[] h = { 1, 2, 3, 3, 3, 3, 6, 6, 6, };
        // 數(shù)組中指定范圍元素重新分配值
        Arrays.fill(h, 0, 2, 9);
        System.out.println("Arrays.fill(h, 0, 2, 9);:");
        // 輸出結(jié)果:993333666
        for (int i : h) {
            System.out.print(i);
        }
        System.out.println();

        /**
         * 轉(zhuǎn)列表 asList()
         */
        // *************轉(zhuǎn)列表 asList()****************
        /*
         * 返回由指定數(shù)組支持的固定大小的列表所灸。
         * (將返回的列表更改為“寫入數(shù)組”。)該方法作為基于數(shù)組和基于集合的API之間的橋梁炫七,與Collection.toArray()相結(jié)合爬立。
         * 返回的列表是可序列化的,并實(shí)現(xiàn)RandomAccess万哪。
         * 此方法還提供了一種方便的方式來創(chuàng)建一個(gè)初始化為包含幾個(gè)元素的固定大小的列表如下:
         */
        List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
        System.out.println(stooges);

        /**
         * 轉(zhuǎn)字符串 toString()
         */
        // *************轉(zhuǎn)字符串 toString()****************
        /*
         * 返回指定數(shù)組的內(nèi)容的字符串表示形式侠驯。
         */
        char[] k = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' };
        System.out.println(Arrays.toString(k));// [a, f, b, c, e, A, C, B]

        /**
         * 復(fù)制 copyOf()
         */
        // *************復(fù)制 copy****************
        // copyOf 方法實(shí)現(xiàn)數(shù)組復(fù)制,h為數(shù)組,6為復(fù)制的長(zhǎng)度
        int[] h2 = { 1, 2, 3, 3, 3, 3, 6, 6, 6, };
        int i[] = Arrays.copyOf(h2, 6);
        System.out.println("Arrays.copyOf(h2, 6);:");
        // 輸出結(jié)果:123333
        for (int j : i) {
            System.out.print(j);
        }
        // 換行
        System.out.println();
        // copyOfRange將指定數(shù)組的指定范圍復(fù)制到新數(shù)組中
        int j[] = Arrays.copyOfRange(h2, 6, 11);
        System.out.println("Arrays.copyOfRange(h2, 6, 11):");
        // 輸出結(jié)果66600(h數(shù)組只有9個(gè)元素這里是從索引6到索引11復(fù)制所以不足的就為0)
        for (int j2 : j) {
            System.out.print(j2);
        }
        // 換行
        System.out.println();

    }
}

3.2 異常

3.2.1 Java異常類層次結(jié)構(gòu)圖
Java異常類層次結(jié)構(gòu)圖

異常分類

所有的異常都有一個(gè)共同的祖先 java.lang 包中的 Throwable 類奕巍。Throwable: 有兩個(gè)重要的子類:Exception(異常) 和 Error(錯(cuò)誤) 吟策,二者都是 Java 異常處理的重要子類,各自都包含大量子類的止。異常和錯(cuò)誤的區(qū)別:異常能被程序本身處理檩坚,錯(cuò)誤是無法處理的。

  • error:
    Error(錯(cuò)誤):是程序無法處理的錯(cuò)誤诅福,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題匾委。大多數(shù)錯(cuò)誤與代碼編寫者執(zhí)行的操作無關(guān),而表示代碼運(yùn)行時(shí) JVM(Java 虛擬機(jī))出現(xiàn)的問題氓润。例如赂乐,Java 虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual MachineError),當(dāng) JVM 不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時(shí)咖气,將出現(xiàn) OutOfMemoryError挨措。這些異常發(fā)生時(shí),Java 虛擬機(jī)(JVM)一般會(huì)選擇線程終止崩溪。
    這些錯(cuò)誤表示故障發(fā)生于虛擬機(jī)自身运嗜、或者發(fā)生在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如 Java 虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual MachineError)悯舟、類定義錯(cuò)誤(NoClassDefFoundError)等。這些錯(cuò)誤是不可查的砸民,因?yàn)樗鼈冊(cè)趹?yīng)用程序的控制和處理能力之 外抵怎,而且絕大多數(shù)是程序運(yùn)行時(shí)不允許出現(xiàn)的狀況。對(duì)于設(shè)計(jì)合理的應(yīng)用程序來說岭参,即使確實(shí)發(fā)生了錯(cuò)誤反惕,本質(zhì)上也不應(yīng)該試圖去處理它所引起的異常狀況。在 Java 中演侯,錯(cuò)誤通過 Error 的子類描述姿染。
  • exception:
    Exception(異常):是程序本身可以處理的異常。Exception 類有一個(gè)重要的子類 RuntimeException。RuntimeException 異常由 Java 虛擬機(jī)拋出悬赏。NullPointerException(要訪問的變量沒有引用任何對(duì)象時(shí)狡汉,拋出該異常)、ArithmeticException(算術(shù)運(yùn)算異常闽颇,一個(gè)整數(shù)除以 0 時(shí)盾戴,拋出該異常)和 ArrayIndexOutOfBoundsException (下標(biāo)越界異常)。
3.2.2 Throwable類常用方法
  • public string getMessage():返回異常發(fā)生時(shí)的簡(jiǎn)要描述
  • public string toString():返回異常發(fā)生時(shí)的詳細(xì)信息
  • public string getLocalizedMessage():返回異常對(duì)象的本地化信息兵多。使用 Throwable 的子類覆蓋這個(gè)方法尖啡,可以生成本地化信息。如果子類沒有覆蓋該方法剩膘,則該方法返回的信息與 getMessage()返回的結(jié)果相同
  • public void printStackTrace():在控制臺(tái)上打印 Throwable 對(duì)象封裝的異常信息
3.2.3 try-catch-finally
  • try塊:用于捕獲異常衅斩。其后可接零個(gè)或多個(gè) catch 塊,如果沒有 catch 塊怠褐,則必須跟一個(gè) finally 塊畏梆。
  • catch塊: 用于處理 try 捕獲到的異常。
  • finally塊:無論是否捕獲或處理異常惫搏,finally 塊里的語句都會(huì)被執(zhí)行具温。當(dāng)在 try 塊或 catch 塊中遇到 return 語句時(shí),finally 語句塊將在方法返回之前被執(zhí)行筐赔。
    在以下四種特殊情況下铣猩,finally塊不會(huì)被執(zhí)行
    • 在 finally 語句塊第一行發(fā)生了異常。 因?yàn)樵谄渌熊罘幔琭inally 塊還是會(huì)得到執(zhí)行
    • 在前面的代碼中用了 System.exit(int)已退出程序达皿。 exit 是帶參函數(shù) ;若該語句在異常語句之后贿肩,finally 會(huì)執(zhí)行
    • 程序所在的線程死亡
    • 關(guān)閉CPU
      注意
      當(dāng) try 語句和 finally 語句中都有 return 語句時(shí)峦椰,在方法返回之前,finally 語句的內(nèi)容將被執(zhí)行汰规,并且 finally 語句的返回值將會(huì)覆蓋原始的返回值汤功。
3.2.4 使用 try-with-resources來代替try-catch-finally
  • 面對(duì)必須要關(guān)閉的資源,我們總是應(yīng)該優(yōu)先使用try-with-resources而不是try-finally溜哮。隨之產(chǎn)生的代碼更簡(jiǎn)短滔金,更清晰,產(chǎn)生的異常對(duì)我們也更有用茂嗓。try-with-resources語句讓我們更容易編寫必須要關(guān)閉的資源的代碼餐茵。 Java 中類似于InputStream瓢湃、OutputStream 亮钦、Scanner 、PrintWriter等的資源都需要我們調(diào)用close()方法來手動(dòng)關(guān)閉驻啤。使用try-with-resources語句就無需手動(dòng)關(guān)閉資源了。
  • 當(dāng)然多個(gè)資源需要關(guān)閉的時(shí)候道批,使用 try-with-resources 實(shí)現(xiàn)起來也非常簡(jiǎn)單错英,如果你還是用try-catch-finally可能會(huì)帶來很多問題。
    通過使用分號(hào)分隔屹徘,可以在try-with-resources塊中聲明多個(gè)資源走趋。
    示例
try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

3.3 多線程

3.3.1 簡(jiǎn)述線程、程序噪伊、進(jìn)程的基本概念簿煌;以及他們之間的關(guān)系

線程

線程與進(jìn)程相似,但線程是一個(gè)比進(jìn)程更小的執(zhí)行單位鉴吹。一個(gè)進(jìn)程在其執(zhí)行的過程中可以產(chǎn)生多個(gè)線程姨伟。與進(jìn)程不同的是同類的多個(gè)線程共享同一塊內(nèi)存空間和一組系統(tǒng)資源,所以系統(tǒng)在產(chǎn)生一個(gè)線程豆励,或是在各個(gè)線程之間作切換工作時(shí)夺荒,負(fù)擔(dān)要比進(jìn)程小得多,線程也被稱為輕量級(jí)進(jìn)程良蒸。

程序

程序是含有指令和數(shù)據(jù)的文件技扼,被存儲(chǔ)在磁盤或其他的數(shù)據(jù)存儲(chǔ)設(shè)備中,也就是說程序是靜態(tài)的代碼嫩痰。

進(jìn)程

進(jìn)程是程序的一次執(zhí)行過程剿吻,是系統(tǒng)運(yùn)行程序的基本單位,因此進(jìn)程是動(dòng)態(tài)的串纺。系統(tǒng)運(yùn)行一個(gè)程序即是一個(gè)進(jìn)程從創(chuàng)建丽旅,運(yùn)行到消亡的過程。
一個(gè)進(jìn)程就是一個(gè)執(zhí)行中的程序纺棺,它在計(jì)算機(jī)中一個(gè)指令接著一個(gè)指令地執(zhí)行著榄笙,同時(shí),每個(gè)進(jìn)程還占有某些系統(tǒng)資源如 CPU 時(shí)間祷蝌,內(nèi)存空間茅撞,文件,輸入輸出設(shè)備的使用權(quán)等等巨朦。換句話說米丘,當(dāng)程序在執(zhí)行時(shí),將會(huì)被操作系統(tǒng)載入內(nèi)存中罪郊。

進(jìn)程和線程的區(qū)別

線程是進(jìn)程劃分成的更小的運(yùn)行單位。線程和進(jìn)程最大的不同在于基本上各進(jìn)程是獨(dú)立的尚洽,而各線程則不一定悔橄,因?yàn)橥贿M(jìn)程中的線程極有可能會(huì)相互影響。
從另一角度來說,進(jìn)程屬于操作系統(tǒng)的范疇癣疟,主要是同一段時(shí)間內(nèi)挣柬,可以同時(shí)執(zhí)行一個(gè)以上的程序,而線程則是在同一程序內(nèi)幾乎同時(shí)執(zhí)行一個(gè)以上的程序段睛挚。

3.3.2 線程的基本狀態(tài)

Java線程運(yùn)行的生命周期

Java線程生命周期中的六種狀態(tài)

Java線程在運(yùn)行的生命周期中的指定時(shí)刻只能處于6種狀態(tài)的其中一個(gè)狀態(tài)邪蛔。

線程之間的狀態(tài)變遷

線程在生命周期中并不是固定處于某一種狀態(tài),隨著代碼執(zhí)行在不同狀態(tài)之間切換扎狱,狀態(tài)變遷圖如下圖所示:

java線程狀態(tài)變遷
  • 初始和運(yùn)行狀態(tài)
    線程創(chuàng)建之后它將處于 NEW(新建) 狀態(tài)侧到,調(diào)用 start() 方法后開始運(yùn)行,線程這時(shí)候處于 READY(可運(yùn)行) 狀態(tài)淤击〗晨梗可運(yùn)行狀態(tài)的線程獲得了 cpu 時(shí)間片(timeslice)后就處于 RUNNING(運(yùn)行) 狀態(tài)。
    操作系統(tǒng)隱藏 Java 虛擬機(jī)(JVM)中的 READY 和 RUNNING 狀態(tài)污抬,它只能看到 RUNNABLE 狀態(tài)汞贸,所以 Java 系統(tǒng)一般將這兩個(gè)狀態(tài)統(tǒng)稱為 RUNNABLE(運(yùn)行中) 狀態(tài) 。


    線程運(yùn)行狀態(tài)
  • 等待印机、超時(shí)等待矢腻、阻塞和終止?fàn)顟B(tài)
    當(dāng)線程執(zhí)行 wait()方法之后,線程進(jìn)入 WAITING(等待)狀態(tài)射赛。進(jìn)入等待狀態(tài)的線程需要依靠其他線程的通知才能夠返回到運(yùn)行狀態(tài)多柑,而 TIME_WAITING(超時(shí)等待) 狀態(tài)相當(dāng)于在等待狀態(tài)的基礎(chǔ)上增加了超時(shí)限制,比如通過 sleep(long millis)方法或 wait(long millis)方法可以將 Java 線程置于 TIMED WAITING 狀態(tài)咒劲。當(dāng)超時(shí)時(shí)間到達(dá)后 Java 線程將會(huì)返回到 RUNNABLE 狀態(tài)顷蟆。當(dāng)線程調(diào)用同步方法時(shí),在沒有獲取到鎖的情況下腐魂,線程將會(huì)進(jìn)入到 BLOCKED(阻塞) 狀態(tài)帐偎。線程在執(zhí)行 Runnable 的run()方法之后將會(huì)進(jìn)入到 TERMINATED(終止) 狀態(tài)。

3.4 文件與I/O流

3.4.1 Java中的IO流分為幾種

Java中IO流分為幾種

  • 按照流的流向分蛔屹,可以分為輸入流和輸出流
  • 按照操作單元分削樊,可以分為字節(jié)流和字符流
  • 按照流的角色分為節(jié)點(diǎn)流和處理流
    節(jié)點(diǎn)流:可以從或向一個(gè)特定的地方(節(jié)點(diǎn))讀寫數(shù)據(jù),如FileReader兔毒。
    處理流:是對(duì)一個(gè)已經(jīng)存在的流的連接和封裝漫贞,通過所封裝的流的功能調(diào)用實(shí)現(xiàn)數(shù)據(jù)讀寫。如BufferedReader育叁。處理流的構(gòu)造方法總是要帶一個(gè)其他的流對(duì)象做參數(shù)迅脐。

Java IO流的類是從下面的4個(gè)抽象類的基類中派生出來的。

  • InputStream/Reader: 所有輸入流的基類豪嗽,前者是字節(jié)輸入流谴蔑,后者是字符輸入流
  • OutputStream/Writer: 所有輸出流的基類豌骏,前者是字節(jié)輸出流,后者是字符輸出流隐锭。

按操作方式分類結(jié)構(gòu)圖

javaIO流按操作方式分類結(jié)構(gòu)圖

按操作對(duì)象分類結(jié)構(gòu)圖

按操作對(duì)象分類結(jié)構(gòu)圖

既然有了字節(jié)流窃躲,為什么還要有字符流

字符流是由 Java 虛擬機(jī)將字節(jié)轉(zhuǎn)換得到的,問題就出在這個(gè)過程還算是非常耗時(shí)钦睡,并且蒂窒,如果我們不知道編碼類型就很容易出現(xiàn)亂碼問題。所以荞怒, I/O 流就干脆提供了一個(gè)直接操作字符的接口洒琢,方便我們平時(shí)對(duì)字符進(jìn)行流操作。如果音頻文件挣输、圖片等媒體文件用字節(jié)流比較好纬凤,如果涉及到字符的話使用字符流比較好。

BIO, NIO和AIO的區(qū)別

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撩嚼,一起剝皮案震驚了整個(gè)濱河市停士,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌完丽,老刑警劉巖恋技,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異逻族,居然都是意外死亡蜻底,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門聘鳞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薄辅,“玉大人,你說我怎么就攤上這事抠璃≌境” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵搏嗡,是天一觀的道長(zhǎng)窿春。 經(jīng)常有香客問我,道長(zhǎng)采盒,這世上最難降的妖魔是什么旧乞? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮磅氨,結(jié)果婚禮上尺栖,老公的妹妹穿的比我還像新娘。我一直安慰自己烦租,他們只是感情好延赌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布货徙。 她就那樣靜靜地躺著,像睡著了一般皮胡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赏迟,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天屡贺,我揣著相機(jī)與錄音,去河邊找鬼锌杀。 笑死甩栈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的糕再。 我是一名探鬼主播量没,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼突想!你這毒婦竟也來了殴蹄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤猾担,失蹤者是張志新(化名)和其女友劉穎袭灯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绑嘹,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稽荧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了工腋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姨丈。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖擅腰,靈堂內(nèi)的尸體忽然破棺而出蟋恬,到底是詐尸還是另有隱情,我是刑警寧澤惕鼓,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布筋现,位于F島的核電站,受9級(jí)特大地震影響箱歧,放射性物質(zhì)發(fā)生泄漏矾飞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一呀邢、第九天 我趴在偏房一處隱蔽的房頂上張望洒沦。 院中可真熱鬧,春花似錦价淌、人聲如沸申眼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽括尸。三九已至巷蚪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間濒翻,已是汗流浹背屁柏。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留有送,地道東北人淌喻。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像雀摘,于是被迫代替她去往敵國(guó)和親裸删。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355