java面向對象編程

1.1.1 類與對象

一個問題?[Demo107.java]

張老太養了兩只貓貓:一只名字叫小白,今年3歲,白色。還有一只叫小花,今年100歲,花色。請編寫一個程序,當用戶輸入小貓的名字時,就顯示該貓的名字,年齡,顏色。如果用戶輸入的小貓名錯誤,則顯示張老太沒有這只貓貓。

//用前面學習過的知識寫出代碼
public class Demo107{
    public static void main(String []args){
        int a=49;//輸入的名字49,50
        int cat1age=3; //第一只貓
        String cat1name="小白";
        String cat1color="白色";
        int cat2age=100; //第二只貓
        String cat2name="小花";
        String cat2color="花色";
        switch(a){
        case '1':
            System.out.println(cat1age+cat1color);
            break;
        case '2':
            System.out.println(cat2age+cat2color);
            break;
        default:
            System.out.println("張老太沒有這只貓!");
        }
    }
}

java語言是面向對象的

計算機語言的發展向接近人的思維方式演變

匯編語言 [面向機器]

c語言 [面向過程]

java語言 [面向對象]

類和對象的關系

把貓的特性提取出來-->貓類-->對象(實例)-->對象(實例)-->...

注意:從貓類到對象,目前有幾種說法:
1、創建一個對象;
2、實例化一個對象;
3、對類實例化...以后大家聽到這些說法,不要模糊。( 對象就是實例,實例就是對象)java最大的特點就是面向對象。

//定義貓類
public class Demo105{
    public static void main(String []args){
        //創建一個貓對象
        Cat cat1=new Cat();//Cat是定義的一個數據類型
        //Cat cat1;
        //cat1=new Cat();// 等同于 Cat cat1=new Cat();
        //訪問屬性的 對象名.屬性名字
        cat1.age=3;
        cat1.name="小白";
        cat1.color="白色";

        //創建第二只貓
        Cat cat2=new Cat();
        cat2.age=100;
        cat2.name="小花";
        cat2.color="花色";  
    }
}

//java中如何定義一個類?[類名的首寫字母大寫]可根據程序的需要定義類
class Cat{
    //下面的就是類的成員變量/屬性
    int agr;
    String name;
    String color;
    Master myMaster;
}

//引用類型,比如建個主人類
class Master{
    int age;
    String name;
    String address;
}

類和對象的區別和聯系

1、類是抽象的,概念的,代表一類事物,比如人類,貓類..

2、對象是具體的,實際的,代表一個具體事物

3、類對象的模板,對象是類的一個個體,實例

-- 如何定義類

一個全面的類定義比較復雜,如:

package 包名;
class 類名 extends 父類 implements
接口名{
 成員變量;
 構造方法;
 成員方法;
}

要透徹的掌握類,必須要了解類的構成

class 類名{ ----> 待定...

  成員變量;

}

1. -- 類的成員變量 :

成員變量是類的一個組成部分,一般是基本數據類型,也可是引用類型。比如我們前面定義貓類的int age 就是成員變量。

2. 對象 -- 如何創建對象 :

創建一個對象有兩種方法

1、先聲明再創建

1 、對象聲明:類名 對象名

2 、對象創建:對象名=new 類名()

2、一步到位法

類名 對象名=new 類名()

對象--如何訪問(使用)對象的成員變量

對象名 . 變量名; // 簡單先這樣理解,以后加下控制符此表達就不準確了。

  • 對象總是存在內存中的

一個小思考題[Demo.105.java]

為了讓大家加深印象,我們定義一個人類(Person)(包括名字、年齡)。用一步到位法去創建一個對象

我們看看下面一段代碼:

System.out.printlin(b.age);

Person a=new Person(); →  請問:b.age究竟是多少?

a.age=10;

a.name="小明";

Person b;

b=a;
  • 對象總是存在內存中的

一個小思考題[Demo106.java]

在明白對象是如何在內存中存在后,請大家再看看下面的思考題,請問會輸出什么信息?

Person1 a=new Person1();

a.age=10;

a.name="小明";

Person1 b;

b=a;

System.out.println(b.name);//輸出“小明”

b.age=200;

System.out.println(a.age);//輸出a.age為200
  • 重點也是難點

類--成員方法的初步介紹

在某些情況下,我們要需要定義成員方法。比如人類:除了有一些屬性外(成員變量表示的年齡、姓名...),我們人類還有一些行為比如:可以說話、跑步..,通過學習,我們人類還可以做算術題。這時就要用成員方法才能完成。現在要求對Person類完善:

1、添加speak成員方法,輸入出:我是一個好人

2、添加jisuan成員方法,可以計算從1+..+1000的結果

3、修改jisuan成員方法,該方法可以接收一個數n,計算從1+..+n的結果

4、添加add成員方法,可以計算兩個數的和

3. -- 類的成員方法 ( 成員函數 ) 定義 :

成員方法也叫成員函數,這里希望大家不要被兩個名詞搞暈了。

public 返回數據類型 方法名(參數列表)
    {
        語句;//方法(函數)主體
    }

1、參數列表:表示成員函數輸入

2、數據類型(返回類型):表示成員函數輸出

3、函數主體:表示為了實現某一功能代碼塊

//類的調用及方法調用[Demo108.java]
public class Demo108{
    public static void main(String []args){
    Person p1=new Person();
    p1.speak();//調用speak方法
    p1.jiSuan();//調用計算方法
    p1.jiSuan(200);//調用可以傳入參數的計算方法
    p1.add(12,10);//調用兩個數的和
    
    int res=p1.add2(23,34);//調用兩個數的和并返回值到res中
    System.out.println("res返回值是:"+res);
    System.out.println("num1+num2+num3="+p1.add3(2,2.3f,4.5f));//返回類型一定要一致否則報錯。
}
}
//定義名字的幾個方法:
//1、駝峰法 如myCry;2、下劃線法my_cry
//方法名在有不同參數的情況下可以使用同一個方法名,即有參數和沒參數的方法可以同名
class Person{ //請注意類名首寫字母應為大寫如Person為類名 
    int age;
    String name;
    //1、可以輸出我是好人方法
    public void speak(){  //請注意方法名的首寫字母應為小寫如speak為方法名
        System.out.println("我是一個好人");
    }
    //2、可以計算1+..+1000的方法
    public void jiSuan(){
        int result=0;
        for(int i=1;i<=1000;i++){
            result=result+i;
        }
    System.out.println("1+..+1000結果是"+result);
    }
    //3、帶參數的成員方法,可以輸入n值并計算1+..+n
    public void jiSuan(int n){
        int result=0;
        for(int i=1;i<=n;i++){
            result+=i;
        }
        System.out.println("1+..+n結果是"+result);
    }
    //4、計算兩個數的和
    public void add(int num1,int num2){
        int result=0;   //與下面一句等同于return num1+num2;
        result=num1+num2;
        System.out.println("num1+num2="+result);
    }
    //5、計算兩個數的和,并將結果返回給主調(調用它的)函數
    //注意:返回類型和返回結果的類型要一致
    //注意:在調用某個成員方法的時候,給出的具體數值的個數
    //和類型要相匹配。
    public int add2(int num1,int num2){
        return num1+num2;
    }
    //6、計算兩個float數的和,并將結果返給主調函數
    public float add3(int num1,float num2,float num3){
        return num1+num2+num3;
    }
}

-- 類的成員方法(函數)--如何理解

如何理解方法這個概念,給大家舉個通俗的示例:

程序員調用方法:給方法必要的輸入,方法返回結果。

類的成員方法-- 聲明 :

public int test(int a);/*方法聲明*/

這句話的作用是聲明該方法,聲明的格式為:

訪問修飾符 數據類型 函數名(參數列表);

在給Person類添加add方法的例題中,我們看到的關鍵字return ,它的功能是把表達式的值返回的值返回給主調函數的方法。

return 表達式;

類的成員方法(函數)--特別說明

1、方法的參數列表可以是多個

案例:在Person類中編寫一個成員方法,從鍵盤輸入三個數,返回最大的那個數。

參數列表可以是多個,并且數據類型可以是任意的類型int float double char..

    訪問修飾符 返回數據類型 函數名(參數列表){
        語句; //函數主體
    }

2、方法可以沒有返回值

案例:編寫一個函數,從控制臺輸入一個整數打印出對應的金字塔。

返回類型可以是任意的數據類型(int,float,double,char..)也可以沒有返回值void表示沒有返回值

    訪問修飾符 返回數據類型 函數名(形參列表){
        語句; //函數主體
    }

類的成員方法(函數)--小練習

案例:編寫一個成員函數,從鍵盤輸入一個整數(1-9),打印出對應的乘法表[Demo110.java]

//實例鍵盤輸入打印乘法表[Demo110.java]
import java.io.*;
public class Demo110{
    public static void main(String []args){
        Cfb jiu=new Cfb();
            jiu.cf();
    }
}
class Cfb{
    public void cf(){
        try{
        //輸入流,從鍵盤接收數
        InputStreamReader isr=new InputStreamReader(System.in);
        BufferedReader br=new BufferedReader(isr);
        //給出提示
        System.out.println("請輸入1-9,按0退出:");
        //從控制臺讀取一行數據
        String a1=br.readLine();
        //把String轉為int
        int num1=Integer.decode(a1);
            for(int i=1;i<=num1;i++){
                for(int j=1;j<=i;j++){
                    System.out.print(i+"×"+j+"="+(i*j)+"\t");
                }
                System.out.println();           
            }
        }catch(Exception e){
          e.printStackTrace();
         }
    }
}

案例:編寫函數,使給定的一個二維數組(3×3)轉置

類定義的完善

在介紹了成員方法后,我們類的定義就可以完善一步:

class 類名{ class 類名{  待定

成員變量; →  成員變量; →        

}  成員方法;

   }

小結:1.先設計類;2.然后根據類創建對象。

小練習:

1、設計計算機類,要求如下:[Demo109.java]

屬性:品牌(Brand)、顏色(Color)、cpu型號(CPU)、內存容量(Memory)、硬盤大小(Harddisk)、價格(Price)、工作狀態(Work)

方法:打開(Open)、關閉(Close)、休眠(Sleep)

創建一個計算機對象,調用打開,關閉方法

//計算機類與對象的代碼
import java.io.*;//加載IO流包
public class Demo109{
    public static void main(String []args){
        Computer Pc=new Computer();
            Pc.Brand="品牌";
            Pc.Color="顏色";
            Pc.Cpu="Cpu型號";
            Pc.Memory="內存容量";
            Pc.Hd="硬盤容量";
            Pc.Price="價格";
            Pc.Work="工作狀態";
            try{
            //輸入流,從鍵盤接收數
            InputStreamReader isr=new InputStreamReader(System.in);
            BufferedReader br=new BufferedReader(isr);
            //給出提示
            System.out.println("請輸入0-9控制機器");
            //從控制臺讀取一行數據
            String a1=br.readLine();
            //把String轉為float
            float num1=Float.parseFloat(a1);
            if(num1==0){Pc.open();}
            else if(num1==1){Pc.close();}
            else if(num1==2){Pc.sleep();}
            else if(num1==3){System.out.println(Pc.Brand);}
            else if(num1==4){System.out.println(Pc.Color);}
            else if(num1==5){System.out.println(Pc.Cpu);}
            else if(num1==6){System.out.println(Pc.Memory);}
            else if(num1==7){System.out.println(Pc.Hd);}
            else if(num1==8){System.out.println(Pc.Price);}
            else if(num1==9){System.out.println(Pc.Work);}
            else {System.out.println("輸入錯誤!");} 
            }catch(Exception e){ 
            e.printStackTrace();
            }
    }
}

class Computer{
    String Brand;
    String Color;
    String Cpu;
    String Memory;
    String Hd;
    String Price;
    String Work;
    public void open(){
        System.out.println("開機");
    }
    public void close(){
        System.out.println("關機");
    }
    public void sleep(){
        System.out.println("休眠");
    }
}

1、 采用面向對象思想設計超級馬里奧游戲人物


1.1.2 構造方法(函數)

類的構造方法介紹

什么是構造方法呢?在回答這個問題之前,我們來看一個需求:前面我們在創建人類的對象時,是先把一個對象創建好后,再給他的年齡和姓名屬性賦值,如果現在我要求,在創建人類的對象時,就直接指定這個對象的年齡和姓名,該怎么做?

你可以在定義類的時候,定義一個構造方法即可。

構造方法是類的一種特殊的方法,它的主要作用是完成對新對象的初始化。它有幾個特點:

1、方法名和類名相同

2、沒有返回值

3、在創建一個類的新對象時,系統會自動的調用該類的構造方法完成對新對象的初始化。

特別說明:

一個類可以定義多個不同的構造方法。

//例人類構造方法[Demo111.java]
public class Demo111{
    public static void main(String []args){
        Person p1=new Person(12,"順平");//給予不同的初始值,調用的構造方法不同,構造方法雖同名,但系統會根據初始值來選定構造方法。
    }
}
//定義一個人類
class Person{
    int age;
    String name;
    //默認構造方法
    public Person(){
    }
    //構造方法的主要用處是:初始化你的成員屬性(變量)
    //構造方法
    public Person(int age,String name){
        System.out.println("我是構造1");
        age=age;
        name=name;
    }
    //構造方法2
    public Person(String name){
        System.out.println("我是構造2");
        name=name;
    }
}

類的默認構造方法

有些同志可能會問?親愛的老師,我們在沒有學習構造函數前不是也可以創建對象嗎?

是這樣的,如果程序員沒有定義構造方法,系統會自動生成一個默認構造方法。比如Person類Person (){};

當創建一個Person對象時Person per1=new Person();默認的構造函數就會被自動調用。

類的構造方法小結:

1 、構造方法名和類名相同;

2 、構造方法沒有返回值;

3 、主要作用是完成對新對象的初始化;

4 、在創建新對象時,系統自動的調用該類的構造方法;

5 、一個類可以有多個構造方法;

6 、每個類都有一個默認的構造方法。

類定義的改進

在提出構造方法后,我們類的定義就應該更加完善了:

class 類名{ class 類名{ class 類名{

成員變量; 成員變量; 成員變量;

} →  成員方法; →  構造方法; →  待定..

 } 成員方法

 }

1.1.3 this

一個問題?

請大家看一段代碼:(Demo112.java)

重點:this是屬于一個對象,不屬于類的。

java虛擬機會給每個對象分配this,代表當前對象。坦白的講,要明白this不是件容易的事

注意事項:this不能在類定義的外部使用,只能在類定義的方法中使用

/*
    this的必要性
*/
public class Demo112{
    public static void main(String []args){
        Dog dog1=new Dog(2,"大黃");
        Person p1=new Person(dog1,23,"郭德綱");
        Person p2=new Person(dog1,24,"劉謙");
        p1.showInfo();  
        p1.dog.showInfo();
    }
}
//定義一個人類
class Person{
    //成員變量
    int age;
    String name;
    Dog dog;//引用類型
    public Person(Dog dog,int age,String name){
        //可讀性不好
        //age=age;
        //name=name;
        this.age=age; //this.age指this代詞指定是成員變量age
        this.name=name; //this.name指this代詞指定是成員變量name
        this.dog=dog;
    }
    //顯示人名字
    public void showInfo(){
        System.out.println("人名是:"+this.name);
    }
}

class Dog{
    int age;
    String name;
    public Dog(int age,String name){
        this.age=age;
        this.name=name;
    }
    //顯示狗名
    public void showInfo(){
        System.out.println("狗名叫"+this.name);
    }
}

類變量--提出問題?

提出問題的主要目的就是讓大家思考解決之道。

public class Demo113{
    public static void main(String []args){
    /*  int total=0;
        Child ch1=new Child(3,"妞妞");
        ch1.joinGame();
        total++;
        Child ch2=new Child(4,"小小");
        ch2.joinGame();
        total++; 
    */
        Child ch1=new Child(3,"妞妞");
        ch1.joinGame();
        Child ch2=new Child(4,"小小");
        ch2.joinGame();
        Child ch3=new Child(5,"大大");
        ch3.joinGame();
        System.out.println("共有="+Child.total);
    }
}
//定義小孩類
class Child{
    int age;
    String name;
    //static公共函數,total是靜態變量,因此它可以被任何一個對象訪問
    static int total=0; 
    public Child(int age,String name){
        this.age=age;
        this.name=name;
    }
    public void joinGame(){
        total++;
        System.out.println("有一個小孩加入了");
    }
}


1.1.4 類變量、類方法

什么是類變量?

類變量是該類的所有對象共享的變量,任何一個該類的對象去訪問它時,取到的都是相同的值,同樣任何一個該類的對象去修改它時,修改的也是同一個變量。

如何定義類變量?

定義語法:

訪問修飾符 static 數據類型 變量名;

如何訪問類變量?

類名 . 類變量名 或者 對象名 . 類變量名

//類變量的程序演示[Demo114.java]
public class Demo114{
    static int i=1;
    static{
        //該靜態區域塊只被執行一次
        i++;
        System.out.println("執行一次");
    }
    public Demo114(){  //建立Demo114()構造函數
        System.out.println("執行二次");
        i++;
    }
    public static void main(String []args){
        Demo114 t1=new Demo114();  //創建t1對象實例并調用Demo114函數
        System.out.println(t1.i);

        Demo114 t2=new Demo114();
        System.out.println(t2.i);
    }
}

什么是類方法,為什么有類方法?

類方法是屬于所有對象實例的,其形式如下:

訪問修飾符 static 數據返回類型 方法名(){}

注意:類方法中不能訪問非靜態變量(類變量)。

使用:類名 . 類方法名 或者 對象名 . 類方法名

重點static靜態的方法可以訪問static靜態變量,不能訪問非靜態變量(類變量)

非靜態方法可以訪問非靜態變量(類變量)同時也可以訪問static靜態變量。

//統計總學費的程序代碼,加深static靜態的方法由靜態變量的訪問[Demo115.java]
public class Demo115{
    public static void main(String []args){
        //創建一個學生
        Stu stu1=new Stu(29,"aa",340);
        Stu stu2=new Stu(29,"aa",240);
        System.out.println(Stu.getTotalFee());
    }
}

//學生類
class Stu{
    int age;
    String name;
    int fee;
    static int totalFee;
    public Stu(int age,String name,int fee){
        this.age=age;
        this.name=name;
        totalFee+=fee;
    }
    //返回總學費[這是一個類方法(靜態方法)]
    //java中規則:類變量原則上用類方法去訪問或操作
    public static int getTotalFee(){
        return totalFee;
    }
}

類變量小結

1、什么時候需要用類變量

案例[Demo115.java]:定義學生類,統計學生共交多少錢?

用類變量,屬于公共的屬性

2、類變量與實例變量區別:

加上static稱為類變量或靜態變量,否則稱為實例變量

類變量是與類相關的,公共的屬性

實例變量屬于每個對象個體的屬性

類變量可以通過 [類名 . 類變量名] 直接訪問

類方法小結

1、什么時候需要用類方法

案例[Demo115.java]:定義學生類,統計學生共交多少錢?

類方法屬于與類相關的,公共的方法

實例方法屬于每個對象個體的方法

類方法可以通過 [類名 . 類方法名] 直接訪問


java 面向對象編程的四大特征

抽象/封裝/繼承/多態

1 抽象 :

1、簡單理解

我們在前面去定義一個類時候,實際上就是把一類事物的共有的屬性和行為提取出來,形成一個物理模型(模版)。這種研究問題的方法稱為抽象。

封裝--什么是封裝

封裝就是把抽象出來的數據和對數據的操作封裝在一起,數據被保護在內部,程序的其它部分只有通過被授權的操作(成員方法),才能對數據進行操作。

封裝--訪問控制修飾符

電視機的開關,對音量,顏色,頻道的控制是公開的,誰都可以操作,但是對機箱后蓋,主機板的操作卻不是公開的,一般是由專業維修人員來玩。那么java中如何實現這種類似的控制呢?不能隨便查看人的年齡,工資等隱私[Demo116.java]

//封裝案例[Demo116.java]
public class Demo116{
    public static void main(String []args){
        //創建一個職員
        Clerk clerk1=new Clerk("小花",24,4567.6f);
        System.out.println("名字是"+clerk1.name+"薪水"+clerk1.getSal());
    }
}
//職員
class Clerk{
    public String name;
    //private私有的,public公有的
    private int age;
    private float salary;

    public Clerk(String name,int age,float sal){
        this.name=name;
        this.age=age;
        this.salary=sal;
    }
    //通過一個成員方法去控制和訪問私有的屬性
    public float getSal(){
        return this.salary;
    }
}

2. 封裝 -- 訪問控制修飾符 :

java提供四種訪問控制修飾符號控制方法和變量的訪問權限:

1 、公開級別:用public修飾,對外公開

2 、受保護級別:用protected修飾,對子類和同一個包中的類公開

3 、默認級別:沒有修飾符號,向同一個包的類公開

4 、私有級別:用private修飾,只有類本身可以訪問,不對外公開

包--必要性

問題的提出,請看下面的一個場景[eclipse]

現在有兩個程序員共同開發一個java項目,程序員xiaoming希望定義一個類取名Dog,程序員xiaoqiang也想定義一個類也叫Dog。兩個程序員為此還吵了起來,怎么辦?

-- 三大作用

1、區分相同名字的類

2、當類很多時,可以很好的管理類

3、控制訪問范圍

-- 換包命令

package com. 自定義名字;

注意:打包命令一般放在文件開始處。

包--命名規范

小寫字母 比如 com.sina.shunping

包--常用的包

一個包下,包含很多的類,java中常用的包有:

java.lang.* 包 自動引入 java.util.* 工具包

java.net.* 包 網絡開發包 java.awt.* 包 窗口工具包

包--如何引入包

語法:import 包;

比如import java.awt.*;

我們引入一個包的主要目的要使用該包下的類

定義類的改進

在提出包后,我們類的定義就更加完善了:

class 類名{ class 類名{ class類名{ package包名; 待定..

成員變量; →  成員變量; →  成員變量; →  class 類名{  →

} 成員方法; 構造方法; 成員變量;

 } 成員方法; 構造方法;

 } 成員方法;

 }

3繼承--為什么有?

//功能:說明繼承的重要性
package com.abc;//包名
public class Demo117 {
    public static void main(String[] args) {
        Pupil p1=new Pupil();
        p1.printName();
    }
}

//將學生的共有屬性提取,做一個父類
class Stu{
    //定義成員屬性
    protected int age;
    public String name;
    public float fee;
    private String job;//私有將不被繼承
    
    //編程中,如果你不希望子類繼承某個屬性或方法
    //則將其聲明為private即可
    public void printName(){
        System.out.println("名字"+this.name);
    }
}

//小學生類
class Pupil extends Stu{
    //交學費
    public void pay(float fee){
        this.fee=fee;
    }
}
//幼兒
class Pre extends Pupil{
    //交學費
    public void pay(float fee){
        this.fee=fee*1.5f;
    }
}
//中學生類
class MiddleStu extends Stu{
    //交學費
    public void pay(float fee){
        this.fee=fee*0.8f;
    }
}
//大學生類
class ColStu extends Stu{
    //交學費
    public void pay(float fee){
        this.fee=fee*0.1f;
    }
}

繼承 -- 解決之道

繼承可以解決代碼復用,讓我們的編程更加靠近人類思維。當多個類存在相同的屬性(變量)和方法時,可以從這些類中抽象出父類(比如剛才的Student),在父類中定義這些相同的屬性和方法,所有的子類不需要重新定義這些屬性和方法,只需要通過extends語句來聲明繼承父類:

語法:class 子類 extends 父類

這樣,子類就會自動擁有父類定義的某些屬性和方法。

繼承--深入討論

1、父類的哪些屬性(變量)、方法被子類繼承了?并不是父類的所有屬性、方法都可以被子類繼承

父類 子類

public 屬性; public 屬性;

protected 屬性; 繼承 protected 屬性;

private 屬性; → 屬性;

屬性;

public 方法; public 方法;

protected 方法; protected 方法;

private 方法; 方法;

方法;

2、結論

從圖可以看出,父類的public修飾符的屬性和方法;protected修飾符的屬性和方法;默認修飾符屬性和方法被子類繼承了,父類的private修飾符的屬性和方法不能被子類繼承。

繼承--注意事項

1、子類最多只能繼承一個父類(指直接繼承)

2、java所有類都是Object類的子類 (所有的子類都可以逐級繼承,例:爺->父->子->孫)

3、JDK6中有202個包3777個類、接口、異常、枚舉、注釋和錯誤

4、在做開發的時候,強烈建議大家多查jdk幫助文檔

5、在使用類時,實在不知道怎么辦,多使用搜索引擎

4. 定義類的改進 :

在提出包后,我們類的定義就更加完善了:

class 類名{ class 類名{ class類名{ package包名;   

成員變量; →  成員變量; →  成員變量; →  class 類名{ 

} 成員方法; 構造方法; 成員變量;

 } 成員方法; 構造方法;

 } 成員方法;

 }  ↓

↓←←←←←←←←←←←←←←←←←←←←←←←←←

package 包名;

class 類名 extends 父類{ 待定

  成員變量; → ....

  構造方法;

  成員方法;

}

1.1.5 方法重載(overload)和方法覆蓋(override)

1 方法重載 (overload)

按順序,我們應該講解多態,但是在講解多態前,我們必須講解方法重載和方法覆蓋(override)。

請編寫一個類(Abc),編寫方法可以接收兩個整數,返回兩個數中較大的數[Demo119.java]

//方法重載(overload)getMax
public class Demo119{
    public static void main(String []args){
        Abc2 abc1=new Abc2();
        System.out.println(abc1.getMax(12,14));
        System.out.println(abc1.getMax(24f,20f));
    }
}

class Abc2{
    //返回較大的整數
    public int getMax(int i,int j){
        if(i>j){
            return i;
        }else{
            return j;
         }
    }
    public float getMax(float a,float b){
        if(a>b){
            return a;
        }else{
            return b;
         }
    }
    //如果只是返回類型不一樣,能否構成重載?不能夠構成重載
/*  public double getMax(float d,double c){
        if(c>d){
            return c;
        }else{
            return d;
         }
    }
    //如果只是控制訪問修飾符不同,能否構成重載?不能夠構成重載
    protected float getMax(float c,float d){
        if(c>d){
            return c;
        }else{
            return d;
         }
    }*/
}

方法重載(overload) 概念

簡單的說:方法重載就是在類的同一種功能的多種實現方式,到底采用哪種方式,取決于調用者給出的參數。

注意事項:

1、方法名相同

2、方法的參數類型,個數,順序至少有一項不同

3、方法返回類型可以不同(只是返回類型不一樣,不能構成重載)

4、方法的修飾符可以不同(只是控制訪問修飾符不同,不能構成重載)

2 方法覆蓋 (override)

既然子類可以繼承父類的屬性和方法,這樣可以提高代碼的復用性,這個很好,可是問題來了,假設現在我要求大家寫三個類貓貓,狗狗,豬豬。我們知道這三個東東都是動物,動物必然存在相同的特點。根據類的抽象特征,我們可以把它們的相同點提取出來,形成一個父類,然后繼承。

//子類方法覆蓋父類方法[Demo120.java]
public class Demo120{
    public static void main(String []args){
        //創建一只貓
        Cat cat1=new Cat();
            cat1.cry();
        Dog dog1=new Dog();
            dog1.cry();
    }
}
//動物類
class Animal{
    int age;
    String name;
    //都會叫
    public void cry(){
        System.out.println("我是動物,不知道怎么叫");
    }

}
//貓貓類
class Cat extends Animal{
    //覆蓋父類方法
    public void cry(){
        System.out.println("貓貓叫!");
    }
}
//狗狗類
class Dog extends Animal{
    //覆蓋父類方法
    public void cry(){
        System.out.println("汪汪叫!");
    }
}

方法覆蓋(override)概念

簡單的說:方法覆蓋就是子類有一個方法,和父類的某個方法的名稱、返回類型、參數一樣,那么我們就說子類的這個方法覆蓋了父類的那個方法。比如上個案例的Cat類中的cry方法就覆蓋了Animal類的cry方法。

注意事項:

方法覆蓋有很多條件,有些書上說的比較細,總的講有兩點一定注意:

1、子類的方法的返回類型,參數,方法名稱,要和父類的返回類型,參數,方法名稱完全一樣,否則編譯出錯。

2、子類方法不能縮小父類方法的訪問權限。

===============================================================================

作業:上機實習題目

1、Josephu問題(丟手帕問題)

Josephu問題為:設編號為1,2,...n的n個人圍坐一圈,約定編號為k(1<=k<=n)的人從1開始報數,數到m的那個人出列,它的下一位又從1開始報數,數到m的那個人又出列,依次類推,直到所有人出列為止,由此產生一個出隊編號的序列。

提示:用一個不帶頭結點的循環鏈表來處理Josephu問題:先構成一個有n個結點的單循環鏈表,然后由k結點起從1開始計數,計到m時,對應結點的人從鏈表中刪除,然后再從被刪除結點的下一個結點又從1開始計數,直到最后一個結點從鏈表中刪除算法結束。

//Josephu問題(丟手帕問題)
//使用單向鏈表
public class Demo121 {
    public static void main(String[] args) {
        CycLink cyclink=new CycLink();
        cyclink.setLen(5);//鏈表長度
        cyclink.createLink();
        cyclink.setK(2);//從第幾個人開始數
        cyclink.setM(2);//數幾下
        cyclink.show();
        cyclink.play();
    }
}

class Child{
    int no;
    Child nextChild=null;
    public Child(int no){
        //給一個編號
        this.no=no;
    }
}

//單向環形鏈表
class CycLink{
    //先定義一個指向鏈表第一個小孩的引用
    //指向第一個小孩的引用,不能動
    Child firstChild=null;
    Child temp=null;
    int len=0;//表示共有多少個小孩
    int k=0;
    int m=0;
    //設置m數幾下
    public void setM(int m){
        this.m=m;
    }
    //設置環形鏈表大小
    public void setLen(int len){
        this.len=len;
    }
    //設置從第幾個人開始數數
    public void setK(int k){
        this.k=k;
    }
    //開始play
    public void play(){
        Child temp=this.firstChild;
        //1.先找到開始數數的人
        for(int i=1;i<k;i++){
            temp=temp.nextChild;
        }
        while(this.len!=1){
            //2.數m下
            for(int j=1;j<m;j++){
                temp=temp.nextChild;
            }
            //找到要出圈的前一個小孩
            Child temp2=temp;
            while(temp2.nextChild!=temp){
                temp2=temp2.nextChild;
            }
            //3.將數到m的小孩,退出圈
            temp2.nextChild=temp.nextChild;
            //讓temp指向下一個數數的小孩
            temp=temp.nextChild;
            this.len--;
        }
        //最后一個小孩
        System.out.println("最后出圈的小孩:"+temp.no);
    }
    
    //初始化單向環形鏈表
    public void createLink(){
        for(int i=1;i<=len;i++){
            if(i==1){
                //創建第一個小孩
                Child ch=new Child(i);
                this.firstChild=ch;
                this.temp=ch;
            }else{
                //創建最后一個小孩
                if(i==len){
                    Child ch=new Child(i);
                    temp.nextChild=ch;
                    temp=ch;
                    temp.nextChild=this.firstChild;
                }else{
                    //繼續創建小孩
                    Child ch=new Child(i);
                    temp.nextChild=ch;
                    temp=ch;    
                }
            }
        }
    }
    //打印該環形鏈表
    public void show(){
        //定義一個跑龍套
        Child temp=this.firstChild;
        do{
            System.out.print(temp.no+" ");
            temp=temp.nextChild;
        }while(temp!=this.firstChild);
    }
}

1.1.6 四大特征

1多態-- 概念

所謂多態,就是指一個引用(類型)在不同情況下的多種狀態。也可以理解成:多態是指通過指向父類的指針,來調用在不同子類中實現的方法。

實現多態有兩種方式:1、繼承;2、接口

多態演示[Dome122.java]

//演示繼承、方法覆蓋、多態
public class Demo122 {
    public static void main(String[] args) {
        //非多態演示
        Cat cat=new Cat();
        cat.cry();
        Dog dog=new Dog();
        dog.cry();
        //多態演示
        Animal an=new Cat();
        an.cry();
        an=new Dog();
        an.cry();
    }
}
//動物類
class Animal{
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    //動物會叫
    public void cry(){
        System.out.println("不知道怎么叫");
    }
}
//創建Dog子類并繼承Animal父類及覆蓋cry方法
class Dog extends Animal{
    //狗叫
    public void cry(){
        System.out.println("汪汪叫");
    }
}
class Cat extends Animal{
    //貓自己叫
    public void cry(){
        System.out.println("貓貓叫");
    }
}

2 多重多態演示[Dome123.java]

//演示子類繼承父類、方法覆蓋、多態方法
public class Demo123 {
    public static void main(String[] args) {
        //非多態演示
        System.out.println("非多態演示:");
        Cat cat=new Cat();
        cat.cry();
        Dog dog=new Dog();
        dog.cry();
        System.out.println();       
        //多態演示
        System.out.println("多態演示:");
        Animal an=new Cat();
        an.cry();
        an=new Dog();
        an.cry();
        System.out.println();   
        //多重多態演示
        System.out.println("多重多態演示:");
        Master master=new Master();
        master.feed(new Dog(),new Bone());
        master.feed(new Cat(),new Fish());
    }
}
//主人類
class Master{
    //給動物喂食物,使用多態,只要寫一個方法
    public void feed(Animal an,Food f){
        an.eat();
        f.showName();
    }
}
//食物父類
class Food{
    String name;
    public void showName(){
        System.out.println("食物");
    }
}
//食物魚子類
class Fish extends Food{
    public void showName(){
        System.out.println("魚");
    }
}
//食物骨頭子類
class Bone extends Food{
    public void showName(){
        System.out.println("骨頭");
    }
}
//動物類Animal父類
class Animal{
    String name;
    int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    //動物會叫
    public void cry(){
        System.out.println("不知道怎么叫");
    }
    //動物吃東西
    public void eat(){
        System.out.println("不知道吃什么");
    }
}
//創建Dog子類并extends繼承Animal父類及覆蓋cry方法
class Dog extends Animal{
    //狗叫
    public void cry(){
        System.out.println("汪汪叫");
    }
    //狗吃東西
    public void eat(){
        System.out.println("狗愛吃骨頭");
    }
}
class Cat extends Animal{
    //貓自己叫
    public void cry(){
        System.out.println("貓貓叫");
    }
    //貓吃東西
    public void eat(){
        System.out.println("貓愛吃魚");
    }
}

3 多態 -- 注意事項:

1、java允許父類的引用變量引用它的子類的實例(對象)

Animal an=new Cat();//這種轉換時自動完成的

2、關于類型轉換還有一些具體的細節要求,我們在后面還要提,比如子類能不能轉換成父類,有什么要求等等...


1.1.7 抽象類

1 抽象類 -- 解決之道

當父類的一些方法不能確定時,可以用abstract關鍵字來修飾該方法[抽象方法],用abstract來修飾該類[抽象類]。

//抽象類的必要性[Demo124.java]
public class Demo124 {
    public static void main(String[] args) {
        //Animal an=new Animal();抽象類不允許實例化
        Animal an=new Cat();
        an.cry();
        an=new Dog();
        an.cry();
    }
}
//抽象類abstract關鍵詞
abstract class Animal{
    String name;
    int age;
    //動物會叫,使用了abstract抽象方法
    abstract public void cry();//抽象類中可以沒有abstract抽象方法
    //抽象類內可以有實現方法
    public void sx(){
        System.out.println("實現方法");
    }
}
//當一個子類繼承的父類是abstract抽象類的話,需要程序員把抽象類的抽象方法全部實現。
class Cat extends Animal{
    //實現父類的cry,其實類似上節學習中的子類覆蓋父類
    public void cry(){
        System.out.println("貓貓叫");
    }
}
class Dog extends Animal{
    //實現父類的cry,其實類似上節學習中的子類覆蓋父類
    public void cry(){
        System.out.println("汪汪叫");
    }
}

2 抽象類 -- 深入討論

抽象類是java中一個比較重要的類。

1 、用abstract關鍵字來修飾一個類時,這個類就是抽象類。

2 、用abstract關鍵字來修飾一個方法時,這個方法就是抽象方法。

3 、abstract抽象類中的abstract抽象方法是不允許在抽象類中實現的,一旦實現就不是抽象方法和抽象類了。abstract抽象方法只能在子類中實現。

4 、抽象類中可以擁有實現方法。

5、抽象方法在編程中用的不是很多,但是在公司筆試時,卻是考官比較愛問的知識點。

3 抽象類****--****注意事項

1 、抽象類不能被實例化

2 、抽象類不一定要包含abstract方法。也就是說,抽象類可以沒有abstract抽象方法。

3 、一旦類包含了abstract抽象方法,則這個類必須聲明為abstract抽象類。

4 、抽象方法不能有主體。

正確的抽象方法例:abstract void abc();

錯語的抽象方法例:abstract void abc(){}

1.1.8 接口

1 接口 -- 為什么有?

USB插槽就是現實中的接口。

什么是接口?

接口就是給出一些沒有內容的方法,封裝到一起,到某個類要使用的時候,在根據具體情況把這些方法寫出來。

接口的建立語法:interface 接口名 { 方法;}

語法:class 類名 implements 接口 {

方法;

變量;

}

小結:接口是更加抽象的抽象的類,抽象類里的方法可以有方法體,接口里的所有方法都沒有方法體。接口體現了程序設計的多態和高內聚低偶合的設計思想。

2 接口 -- 注意事項

1、接口不能被實例化

2、接口中所有的方法都不能有主體。錯誤語法例:void aaa(){}←(注意不能有花括號)

接口可以看作更加抽象的抽象類。

3、一個類可以實現多個接口

4、接口中可以有變量[但變量不能用private和protected修飾]

a、接口中的變量,本質上都是static的而且是final類型的,不管你加不加static修飾

b、在java開發中,我們經常把常用的變量,定義在接口中,作為全局變量使用

訪問形式:接口名 . 變量名

5、一個接口不能繼承其它的類,但是可以繼承別的接口

//接口的實現[Demo125.java]
//電腦,相機,u盤,手機

//usb接口
interface Usb{
    int a=1;//加不加static都是靜態的,不能用private和protected修飾
    //聲明了兩個方法
    public void start();//接口開始工作
    public void stop();//接口停止工作
}
//編寫了一個相機類,并實現了usb接口
//一個重要的原則:當一個類實現了一個接口,要求該類把這個接口的所有方法全部實現
class Camera implements Usb{
    public void start(){
        System.out.println("我是相機,開始工作了..");
    }
    public void stop(){
        System.out.println("我是相機,停止工作了..");
    }
}
//接口繼承別的接口
class Base{
}
interface Tt{
}
interface Son extends Tt{
}
//編寫了一個手機,并實現了usb接口
class Phone implements Usb{
    public void start(){
        System.out.println("我是手機,開始工作了..");
    }
    public void stop(){
        System.out.println("我是手機,停止工作了..");
    }
}
//計算機
class Computer{
    //開始使用usb接口
    public void useUsb(Usb usb){
        usb.start();
        usb.stop();
    }
}
public class Demo125 {
    public static void main(String[] args) {
        System.out.println(Usb.a);
        //創建 Computer
        Computer computer=new Computer();
        //創建Camera
        Camera camera1=new Camera();
        //創建Phone
        Phone phone1=new Phone();
        computer.useUsb(camera1);
        computer.useUsb(phone1);
    }
}

3 定義類的改進

有了接口,我們類的定義就更加完善了:

class 類名{ class 類名{ class類名{ package包名;   

成員變量; →  成員變量; →  成員變量; →  class 類名{ 

} 成員方法; 構造方法; 成員變量;

 } 成員方法; 構造方法;

 } 成員方法;

 }  ↓

↓←←←←←←←←←←←←←←←←←←←←←←←←←

package 包名; package 包名;

class 類名 extends 父類{ class 類名 extends 父類 implements 接口名{

  成員變量;    →  成員變量;

  構造方法; 構造方法;

  成員方法; 成員方法;

} }

4 實現接口VS繼承類

java的繼承是單繼承,也就是一個類最多只能有一個父類,這種單繼承的機制可保證類的純潔性,比C++中的多繼承機制簡潔。但是不可否認,對子類功能的擴展有一定影響。所以:

1、實現接口可以看作是對繼承的一種補充。(繼承是層級式的,不太靈活。修改某個類就會打破繼承的平衡,而接口就沒有這樣的麻煩,因為它只針對實現接口的類才起作用)

2、實現接口可在不打破繼承關系的前提下,對某個類功能擴展,非常靈活。

//實例:建立子類并繼承了父類且連接多個接口[Demo126.java]
public class Demo126 {
    public static void main(String[] args) {
        System.out.println("繼承了Monkey父類");
        Monkey mo=new Monkey();
        mo.jump();
        LittleMonkey li=new LittleMonkey();
        li.swimming();
        li.fly();
    }
}
//接口Fish
interface Fish{
    public void swimming();
}
//接口Bird
interface Bird{
    public void fly();
}
//建立Monkey類
class Monkey{
    int name;
    //猴子可以跳
    public void jump(){
        System.out.println("猴子會跳!");
    }
}
//建立LittleMonkey子類并繼承了Monkey父類并連接了Fish和Bird接口
class LittleMonkey extends Monkey implements Fish,Bird{
    public void swimming() {
        System.out.println("連接了Fish接口!");
    }
    public void fly() {
        System.out.println("連接了Bird接口!");
    }
}

5 用接口實現多態--案例[Demo127.java]

java中多態是個難以理解的概念,但同時又是一個非常重要的概念。java三大特性之一(繼承,封裝,多態),我們可以從字面上簡單理解:就是一種類型的多種狀態,以下通過賣小汽車的例子說明什么是多態。

//用接口實現多態
public class Demo127 {
    public static void main(String []args){
        CarShop aShop=new CarShop();
        //賣出一輛寶馬
        aShop.sellCar(new BMW());
        //賣出一輛奇瑞QQ
        aShop.sellCar(new CheryQQ());
        //賣出一輛桑塔納
        aShop.sellCar(new Santana());
        System.out.println("總收入:"+aShop.getMoney());
    }
}
//汽車接口
interface Car{
    //汽車名稱
    String getName();
    //獲得汽車售價
    int getPrice();
}
//寶馬
class BMW implements Car{
    public String getName(){
        return "BMW";
    }
    public int getPrice(){
        return 300000;
    }
}
//奇瑞QQ
class CheryQQ implements Car{
    public String getName(){
        return "CheryQQ";
    }
    public int getPrice(){
        return 20000;
    }
}
//桑塔納汽車
class Santana implements Car{
    public String getName(){
        return "Santana";
    }
    public int getPrice(){
        return 80000;
    }
}
//汽車出售店
class CarShop{
    //售車收入
    private int money=0;        
    //賣出一部車
    public void sellCar(Car car){
        System.out.println("車型:"+car.getName()+"單價:"+car.getPrice

());
        //增加賣出車售價的收入
        money+=car.getPrice();
    }
    //售車總收入
    public int getMoney(){
        return money;
    }
}

運行結果:

車型:BMW 單價:300000

車型:CheryQQ 單價:20000

總收入:320000

繼承是多態得以實現的基礎。從字面上理解,多態就是一種類型(都是Car類型)表現出多種狀態(寶馬汽車的名稱是BMW,售價是300000;奇瑞汽車的名稱是CheryQQ,售價是2000)。將一個方法調用同這個方法所屬的主體(也就是對象或類)關聯起來叫做綁定,分前期綁這下和后期綁定兩種。下面解釋一下它們的定義:

1 、前期綁定:在程序運行之前進行綁定,由編譯器和連接程序實現,又叫做靜態綁定。比如static方法和final方法,注意,這里也包括private方法,因為它是隱式final的。

2 、后期綁定:在運行時根據對象的類型進行綁定,由方法調用機制實現,因此又叫做動態綁定,或者運行時綁定。除了前期綁定外的所有方法都屬于后期綁定。

多態就是在后期綁定這種機制上實現的。多態給我們帶來的好處是消除了類之間的偶合關系,使程序更容易擴展。比如在上例中,新增加一種類型汽車的銷售。只需要讓新定義的類實現Car類并實現它的所有方法,而無需對原有代碼做任何修改,CarShop類的sellCar(Car

car)方法就可以處理新的車型了。

新增代碼如下:

java代碼

//桑塔納汽車
class Santana implements Car{
    public String getName(){
        return "Santana";
    }
    public int getPrice(){
        return 80000;
    }
}

1.1.9 final

final概念

final中文意思:最后的,最終的。

final可以修飾變量或者方法。

在某些情況下,程序員可能有以下需求:

1 、當不希望父類的某個方法被子類覆蓋(override)時,可以用final關鍵字修飾。

2 、當不希望類的某個變量的值被修改,可以用final修飾。如果一個變量是final,則必須賦初值,否則編譯出錯。

3 、當不希望類被繼承時,可以用final修飾。

//final方法的使用[Demo128.java]
public class Demo128 {
    public static void main(String[] args) {
        Aaa aaa=new Aaa();
        aaa.show();
        Bbb bbb=new Bbb();
        bbb.show();
    }
}
class Aaa{ 
    int a=0;//如果a不賦初值,a是0。定義類型后應賦值
    //圓周率不讓修改
    //帶有final修飾的變量命名時應有_下劃線來區分表示。這是java程序員的標準。
    final float reate_1=3.1415926f;//使用final可以保證,需要強制不被修改的數據一定要用final鎖定
    //final int b;  //使用final定義變量時一定要賦初值否則報錯。
    //b=1;
    final public void sendMes(){//給成員方法用final來修飾則表示不可以被修改,不可被覆蓋。
        System.out.println("發送消息");
    }
    public void show(){
        System.out.println("a="+a);
    }
}
final class Bbb extends Aaa{//定義類前加final表示該類不允許被繼承
    public Bbb(){
        a++;
        //reate_1=reate+1;
    }
    /*public void sendMes(){
        System.out.println("發送消息")
    }*/
}

final-- 注意事項

1、final修飾的變量又叫常量,一般用XX_XX_XX來命名。(帶下劃線)

2、final修飾的變量在定義時,必須賦值,并且以后不能再賦值。

final-- 什么時候用

1、因為案例的考慮,類的某個方法不允許修改。

2、類不會被其它的類繼承。

3、某些變量值是固定不變的,比如圓周率3.1415926

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容