別再說你不懂java面向對象了慰丛,阿里P7大佬一次性給你講的明明白白

前言

面向對象在百度百科中是這樣解釋的:“面向對象是一種對現(xiàn)實世界理解和抽象的方法,是計算機編程技術發(fā)展到一定階段后的產(chǎn)物”套鹅。說的好像很流弊的樣子站蝠,看看就行。

包的認識

1.1:包的概念
包是組織卓鹿、整合類的一種方式
其目的在于保證使用類的唯一性(同一個包中菱魔,里面所包含的類名是唯一的)
比如在包A中定義了一個Test類,在包B中也定義了一個Test類吟孙,那么當使用A中的Test類時便導入包A調(diào)用A中的Test類(A.Test)澜倦,以此保證類的唯一性。

1.2:導入包中的類
Java中有很多現(xiàn)成的包供我們使用杰妓,使用這些包的方式有兩種

public class TestDemo {
    public static void main(String[] args) {
        java.util.Date time = new java.util.Date();
        //使用 util 包中的Date類創(chuàng)建一個對象
        System.out.println(time.getTime());
        //調(diào)用該對象的 getTime 方法藻治,獲得一個毫秒級別的時間戳
    }
}

上述代碼中,util 就是一個包巷挥,Date就是該包中的一個類桩卵,使用時用 java.包名.類名 使用

import java.util.Date;
public class TestDemo {
    public static void main(String[] args) {
        Date time = new Date();
        System.out.println(time.getTime());
    }

第一個代碼每次使用類時都要加包的前綴,太過麻煩倍宾,因此還可使用第二種方式雏节,在代碼最開頭使用 import 關鍵字導入需要的包,這樣就可以像使用自己定義的類一樣高职,直接用類名創(chuàng)建對象
當同時需要同一個包中的多個類是钩乍,可以用 import.java.包名.* 的方式導入包,這樣就可以使用該包下的所有類(但建議不要這么使用怔锌,否則當導入多個包時還是會出現(xiàn)類名重復的現(xiàn)象)寥粹。

1.3:靜態(tài)導入
包中除了類的普通方法外,還有一些靜態(tài)方法产禾,使用這些方法時排作,可以使用 import static 的方式導入包中的靜態(tài)字段和方法,無需創(chuàng)建對象直接使用

import static java.lang.Math.*;
public class TestDemo {
    public static void main(String[] args) {
        double x = 10.5;
        double y = 3.0;
        double result = sqrt(pow(x,y)+pow(x,y));
        System.out.println(result);
    }

1.4:自定義類放入包中
基本規(guī)則

  • 在文件的最上方加一個 package 語句指定該代碼在哪個包中
  • 包名盡量指定成唯一名字亚情,防止多文件間沖突
  • 包名和代碼路徑相匹配
  • 如果一個類沒有 package 語句妄痪,則該類會被放到默認包中

1.5:包的訪問權限控制
如果某個成員不包含 public 和 private 關鍵字,此時這個成員可以被包中的其他類使用楞件,但不能在包外部類中使用

1.6:常見的系統(tǒng)包
1衫生、java.lang:系統(tǒng)常用基礎類(String裳瘪,Object)挺举,jdk1.1以后自動導入
2慎宾、java.lang.reflect: java 反射編程包
3桐磁、java.net:進行網(wǎng)絡編程開發(fā)包
4驼鞭、java.sql:進行數(shù)據(jù)庫開發(fā)的支持包。
5蝎困、java.util:是java提供的工具程序包离赫。(集合類等)
6坚踩、java.io:I/O編程開發(fā)包墓阀。

繼承

2.1 概念:
當創(chuàng)建多個類時發(fā)現(xiàn)這些類之間存在一定的關聯(lián)關系毡惜,則可以創(chuàng)建一個父類擁有這些類的相同屬性和方法,讓這些類繼承與父類斯撮,來提高效率经伙,達到代碼重用的效果。
此時被繼承的類我們成為 父類勿锅、基類或者超類帕膜,而繼承的類我們稱為子類或者派生類,子類會繼承父類除構造方法外的其他所有東西溢十。
2.2 語法規(guī)則:
class 子類 extend 父類{

}

  • 子類使用 extend 關鍵字繼承父類
  • Java中一個子類只能繼承一個父類
  • 子類會繼承父類的所有 public 的字段和方法
  • 對于父類的 private 的字段和方法垮刹,子類無法訪問
  • 子類實例中也包含父類實例,可使用 super 關鍵字得到父類的引用
class Animal{
    public String name;//父類的name必須為 public 否則子類將無法訪問
    public Animal(String name) {
        this.name = name;
    }

    public void eat(String food){
        System.out.println(this.name+"吃"+food);
    }
}
class Dog extends Animal{
    public Dog(String name){
        super(name);
    }
}

class Bird extends Animal{
    public Bird(String name){
        super(name);
    }
    public void fly(){
        System.out.println(this.name+"正在飛");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Dog dog = new Dog("旺旺");
        dog.eat("骨頭");
        Bird bird = new Bird("啾啾");
        bird.eat("米粒");
        bird.fly();
    }

2.3茶宵、protected關鍵字
上述代碼中危纫,如果將父類的 name 設為 private子類將無法訪問宗挥,但設為 public 又違背了封裝的規(guī)則乌庶,此時就需要用到 protect 關鍵字

  • 對于其他類的調(diào)用者來說,被 protect 修飾的字段和方法是不能被訪問的
  • 但對于 該類的子類同一個包下的其他類 來說契耿,被 protect 修飾的字段和方法是可以被訪問的

小結:Java中對字段和方法共有四種訪問權限

  • private:只能在類內(nèi)部訪問瞒大,內(nèi)外部一律不行
  • 默認:在類內(nèi)部能訪問,同一個包中的類也可以訪問
  • protect:在類內(nèi)部能訪問搪桂,且在其子類和同一個包中的類也可以訪問
  • public:類內(nèi)部和類的調(diào)用者都能訪問

2.4透敌、final關鍵字
final 可以修飾一個變量或者字段,用來表示常量
final 也惡意修飾一個類踢械,用來表現(xiàn)該類不能被繼承
組合:
即一個類中對另一個類的嵌套酗电,在一個類中實例另一個類,達到代碼重用的效果

多態(tài)

3.1内列、向上轉型:
如上代碼撵术,創(chuàng)建一個 Bird 的對象可以寫成

Bird bird = new Bird();

也可以寫成

Bird bird = new Bird()话瞧;
Animal bird2 = bird嫩与;
Animal bird3 = new Bird()寝姿;

此時bird2、bird3是一個父類(Animal)的引用划滋,指向子類(bird)的實例饵筑,這稱為向上轉型。
向上轉型發(fā)生的時機:

  • 直接賦值(即上述代碼演示)
  • 方法傳參
  • 方法返回

方法傳參:

public static void main(String[] args) {
    Bird bird = new Bird("啾啾");
    feed(bird);
}
public static void feed(Animal animal){
    animal.eat("谷子");
}

此時形參的類型是 Animal(父類) ,實際上是對應到 Bird(子類)的實例

方法返回:

public static void main(String[] args) {
    findAnimal().eat("谷子");
}
public static Animal findAnimal(){
    Bird bird = new Bird("啾啾");
    return bird;
}

方法 findAnimal 返回值是 Animal 的一個引用处坪,但實際指向 Bird 的一個實例

3.2:動態(tài)綁定
子類和父類出現(xiàn)同名方法時發(fā)生

class Animal{
    public String name;
    public Animal(String name) {
        this.name = name;
    }

    public void eat(String food){
        System.out.println("我是一只小動物");
        System.out.println(this.name+"正在吃"+food);
    }
}
class Bird extends Animal{
    public Bird(String name){
        super(name);
    }
    public void eat(String food){
        System.out.println("我是一只小鳥");
        System.out.println(this.name+"正在吃"+food);
    }
    public void fly(){
        System.out.println(this.name+"正在飛");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Animal animal1 = new Animal("動物");
        Animal animal2 = new Bird("小鳥");
        animal1.eat("谷子");
        animal2.eat("谷子");
    }

執(zhí)行以上代碼我們發(fā)現(xiàn):

  • animal1 和 animal2 雖然都是 Animal 類型的引用根资,但animal1指向 Animal 實例的對象,animal2指向 Bird 實例的對象
  • 對 animal1 和 animal2 分別調(diào)用eat方法同窘,發(fā)現(xiàn) animal1 調(diào)用的是父類的方法嫂冻,animal2 調(diào)用的是子類的方法

在Java中,調(diào)用某個方法塞椎,究竟執(zhí)行哪段代碼(是父類方法還是子類)桨仿,取決于看這個引用指向的對象是父類對象還是子類對象,這個過程是在運行時才決定的案狠,因此成為動態(tài)綁定
父類引用服傍,引用子類對象時,只能訪問自己特有的骂铁,不能訪問子類獨有的

3.3吹零、重寫
對于上述代碼,父類和子類的eat方法來說拉庵,就構成了重寫
重寫的注意事項:

  • 普通方法可以重寫灿椅,static 修飾的方法不能重寫
  • 重寫中子類的訪問權限不能低于父類的訪問權限
  • 重寫和重載不同

重寫和重載的區(qū)別

1.要求不同
重載:a.方法名相同 b.參數(shù)列表不同 c.返回值不做要求
重寫:a.方法名相同 b.參數(shù)列表相同(參數(shù)類型和個數(shù)) c.返回值也要相同
2.范圍不同
重載:同一個類中
重寫:繼承關系,不同類中
3.限制
重載:無限制
重寫:子類中重寫的方法訪問權限不能低于父類的訪問權限

3.4钞支、理解多態(tài)

class Shape {
    public void draw(){

    }
}
class Circle extends Shape{
    public void draw(){
        System.out.println("畫一個圓圈○");
    }
}
class Rectangle extends Shape{
    public void draw(){
        System.out.println("畫一個矩形□");
    }
}
class Triangle extends Shape{
    public void draw(){
        System.out.println("畫一個三角△");
    }
}
//================================================
//================================================
public class TestDemo {
    public static void main(String[] args) {
        Shape shape1 = new Circle();
        Shape shape2 = new Rectangle();
        Shape shape3 = new Triangle();
        drawMap(shape1);
        drawMap(shape2);
        drawMap(shape3);
    }
    public static void drawMap(Shape shape){
        shape.draw();
    }

以上代碼茫蛹,分割線以上是由類的實現(xiàn)者編寫的,分割線以下是由類的調(diào)用者編寫的
當調(diào)用者編寫drawMap方法的時候(參數(shù)類型為父類Shape)烁挟,并不關心當前shape引用指向哪個類型的實例婴洼,此時shape調(diào)用的draw方法只取決于shape指向的哪個類型的實例,以實現(xiàn)不同的表現(xiàn)形式撼嗓,這種思想叫做多態(tài)柬采。

3.5、向下轉型
父類引用且警,引用子類對象稱為向上轉型粉捻;子類引用,引用父類對象稱為向下轉型斑芜。

class Animal{
    public String name;
    public Animal(String name) {
        this.name = name;
    }

    public void eat(String food){
        System.out.println("我是一只小動物");
        System.out.println(this.name+"正在吃"+food);
    }
}

ass Bird extends Animal{
    public Bird(String name){
        super(name);
    }
    public void eat(String food){
        System.out.println("我是一只小鳥");
        System.out.println(this.name+"正在吃"+food);
    }
    public void fly(){
        System.out.println(this.name+"正在飛");
    }
}
    public class TestDemo {
    public static void main(String[] args) {
        Animal animal = new Bird("啾啾");
        animal.eat("谷子");
        animal.fly();//執(zhí)行該行代碼時肩刃,會報錯誤
    }

編譯過程中 animal 的類型時 Animal ,編譯器編譯時根據(jù)類型只知道 animal 中只有一個eat方法,找不到fly方法

  • 編譯器檢查存在哪些方法時候树酪,看的是 Animal 類型
  • 執(zhí)行時究竟執(zhí)行父類方法還是子類方法浅碾,看的是 Bird 類型
    但很多時候為了讓向下轉型更安全,需要判斷一下 animal 是否指向 Bird 的引用续语,使用instanceof 關鍵字判斷
Animal animal = new Cat("小貓");
if (animal instanceof Bird) {
Bird bird = (Bird)animal;
bird.fly();
}

3.6垂谢、super關鍵字
當在子類內(nèi)部要調(diào)用父類方法時,就要用到 super 關鍵字
super 表示獲取到父類實例的引用疮茄,其有兩種常用方法

一滥朱、使用 super 來調(diào)用父類的構造方法,super(參數(shù))

public Bird(String name){
    super(name);
}

二力试、使用 super 來調(diào)用父類的普通方法徙邻,super.方法名(參數(shù))

class Bird extends Animal{
    public Bird(String name){
        super(name);
    }
    public void eat(String food){
        super.eat(food);
        System.out.println("我是一只小鳥");
        System.out.println(this.name+"正在吃"+food);
    }
}

上述代碼中個,如果直接調(diào)用eat方法畸裳,則被編譯器認為是調(diào)用子類的方法(同遞歸)缰犁,想要調(diào)用父類方法則需要使用 super 關鍵字

this和super的區(qū)別:

1、概念
this:訪問本類的屬性和方法
super:訪問父類的屬性和方法
2怖糊、查找范圍
this:先查找本類帅容,子類沒有再調(diào)用父類
super:不查找本類,直接調(diào)用父類
3伍伤、特殊
this:表示當前對象的引用
super:表現(xiàn)父類對象的引用

多態(tài)存在的意義就在于并徘,讓調(diào)用者不必關注對象的具體類型,降低用戶的使用成本

4扰魂、抽象類

4.1語法規(guī)則
類似于之前代碼的父類 Shape 中的draw方法麦乞,其中并沒有實際工作,而由其子類重新該方法實現(xiàn)劝评,那么像這種沒有實際工作的方法我們就可以用 abstract 關鍵字修飾把它設計成一個抽象方法姐直,而包含抽象方法的類我們就稱為抽象類

abstract class Shape {
   abstract public void draw();
}
  • 在draw方法前加一個 abstract 修飾表示該方法是抽象方法,抽象方法沒有方法體
  • 對于包含抽象方法的類付翁,class 前必須加一個 abstract 關鍵字表示是抽象類

注意事項:

  • 抽象類不能直接實例
  • 抽象方法的訪問權限不能是private
  • 抽象類中可以包含其他非抽象方法简肴,也可以包含字段晃听,和普通方法一樣百侧,可以被重新可以被調(diào)用

4.2抽象類的作用
抽象類的意義在于為了被繼承
抽象類本身不能實例化,想要使用能扒,必須創(chuàng)建該抽象類的子類佣渴,在子類中重寫抽象方法
使用抽象類相當于多了一重編譯器的檢驗(對于抽象了來說,如果繼承的子類不重寫父類的抽象方法初斑,則會報錯)

5辛润、接口

接口是比抽象類還抽象,接口只包含抽象方法见秤,其字段也只能包含靜態(tài)常量

interface IShape{
    abstract public void draw();
}

class Circle implements Shape{
    @Override
    public void draw() {
        System.out.println();
    }
}
  • 用 interface 定義一個接口
  • 接口中的方法只能是抽象方法砂竖,所以可以省略 abstract
  • 并且接口中的方法只能是 public 真椿,所以可以省略
  • Circle 用 implement 來實現(xiàn)接口
  • 在調(diào)用的時候同樣可以創(chuàng)建一個接口的引用,對應到一個子類的實例
  • 接口不能被單獨實例化

在Java中一個類只能繼承一個父類乎澄,但同時可以實現(xiàn)多個接口

class Animal{
    public String name;
    public Animal(String name){
        this.name = name;
    }
}
interface IFlying{
    void fly();
}
interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}
class Dog extends Animal implements IRunning{
    public Dog(String name){
        super(name);
    }
    @Override
    public void run() {
        System.out.println(this.name+"正在跑步");
    }
}
class Frog extends Animal implements IRunning,ISwimming{
    public Frog(String name){
        super(name);
    }
    @Override
    public void run() {
        System.out.println(this.name+"正在跑步");
    }
    @Override
    public void swim() {
        System.out.println(this.name+"正在游泳");
    }
}
class Duck extends Animal implements IRunning,ISwimming,IFlying{
    public Duck(String name){
        super(name);
    }
    @Override
    public void fly() {
        System.out.println(this.name+"正在飛");
    }
    @Override
    public void run() {
        System.out.println(this.name+"正在游泳");
    }
    @Override
    public void swim() {
        System.out.println(this.name+"正在游泳");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Dog dog = new Dog("汪汪");
        Frog frog = new Frog("呱呱");
        Duck duck = new Duck("嘎嘎");
        dog.run();
        frog.run();
        frog.swim();
        duck.fly();
        duck.run();
    }
}

接口使用實例——給對象數(shù)組排序
創(chuàng)建一個學生類

class Students implements Comparable{
    private String name;
    private int score;
    public Students(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Students{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        Students s = (Students)o;
        if(s.score > ((Students) o).score){
            return 1;
        }else if(s.score == ((Students) o).score){
            return 0;
        }else{
            return -1;
        }
    }
}

在 sort 方法中會自動調(diào)用 compareTo 方法.compareTo 的參數(shù)是 Object突硝,其實傳入的就是Students類型的對象,然后比較當前對象和參數(shù)對象的大小關系

接口間的承接
一個接口可以承接另一個接口置济,達到復用效果解恰,使用 extends 關鍵字
接口間承接相當于把多個接口憑借在一起

Clonable 接口和深拷貝
Object 類中存在一個 clone 方法,調(diào)用這個方法可以創(chuàng)建一個對象的“拷貝”浙于,但是想要合法的調(diào)用clone方法护盈,必須先要實現(xiàn) Clonable 接口,否則就會拋出 CloneNotSupportedException 異常

class Person implements Cloneable{
    public String name;

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("小明");
        Person person2 = (Person) person1.clone();
        person2.name = "小紅";
        System.out.println(person1);
        System.out.println(person2);
    }
}

如下代碼即深拷貝:

class Money implements Cloneable{
    public int m=10;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public String name;
    public Money money ;

    public Person(String name) {
        this.name = name;
        this.money = new Money();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        person.money = (Money) this.money.clone();
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", money=" + money.m +
                '}';
    }
}

public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("小明");
        Person person2 = (Person) person1.clone();
        person2.name = "小紅";
        person2.money.m = 15;
        System.out.println(person1);
        System.out.println(person2);
    }
}

總結

  • 抽象類和接口都是Java中多態(tài)的常見使用方法羞酗,但兩者又有區(qū)別
    最核心區(qū)別:抽象類可以包含普通方法和普通字段腐宋,可以被子類直接使用,而接口中只有抽象方法檀轨,實現(xiàn)該接口的類必須重寫所有抽象方法

最后

感謝你看到這里脏款,看完有什么的不懂的可以在評論區(qū)問我,覺得文章對你有幫助的話記得給我點個贊裤园,每天都會分享java相關技術文章或行業(yè)資訊撤师,歡迎大家關注和轉發(fā)文章!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拧揽,一起剝皮案震驚了整個濱河市剃盾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淤袜,老刑警劉巖痒谴,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異铡羡,居然都是意外死亡积蔚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門烦周,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尽爆,“玉大人,你說我怎么就攤上這事读慎∈” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵夭委,是天一觀的道長幅狮。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么崇摄? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任擎值,我火速辦了婚禮,結果婚禮上逐抑,老公的妹妹穿的比我還像新娘幅恋。我一直安慰自己,他們只是感情好泵肄,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布捆交。 她就那樣靜靜地躺著,像睡著了一般腐巢。 火紅的嫁衣襯著肌膚如雪品追。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天冯丙,我揣著相機與錄音肉瓦,去河邊找鬼。 笑死胃惜,一個胖子當著我的面吹牛泞莉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播船殉,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼鲫趁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了利虫?” 一聲冷哼從身側響起挨厚,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎糠惫,沒想到半個月后疫剃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡硼讽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年巢价,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片固阁。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡壤躲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出您炉,到底是詐尸還是另有隱情柒爵,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布赚爵,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏冀膝。R本人自食惡果不足惜唁奢,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窝剖。 院中可真熱鬧麻掸,春花似錦、人聲如沸赐纱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疙描。三九已至诚隙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間起胰,已是汗流浹背久又。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留效五,地道東北人地消。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像畏妖,于是被迫代替她去往敵國和親脉执。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350