java 反射全面總結(jié)

反射總結(jié)
慕課網(wǎng) 反射的視頻

什么是反射

反射是能夠讓java代碼訪問一個已經(jīng)加載的類的字段割择,變量,方法和構(gòu)造器等信息慎式,并能夠訪問他們不受訪問權(quán)限的控制安接,即能訪問私有構(gòu)造方法屬性等

什么是Class

Class
因為 Java 是面向?qū)ο蟮恼Z言,基本上是以類為基礎(chǔ)構(gòu)造了整個程序系統(tǒng)雾家,反射中要求提供的規(guī)格說明書其實就是一個類的規(guī)格說明書铃彰,它就是 Class。
注意的是 Class 是首字母大寫榜贴,不同于 class 小寫豌研,class 是定義類的關(guān)鍵字,而 Class 的本質(zhì)也是一個類唬党,因為在 Java 中一切都是對象鹃共。

Class 就是一個對象,它用來代表運行在 Java 虛擬機(jī)中的類和接口驶拱。
把 Java 虛擬機(jī)類似于高速公路霜浴,那么 Class 就是用來描述公路上飛馳的汽車,也就是我前面提到的規(guī)格說明書蓝纲。

獲取反射對象的三種方法

反射的入口是 Class阴孟,但是反射中 Class 是沒有公開的構(gòu)造方法的,所以就沒有辦法像創(chuàng)建一個類一樣通過 new 關(guān)鍵字來獲取一個 Class 對象

任何一個類都是Class類的實例對象税迷,這個實例對象有三種表示方式:(我們新建一個Student類)
Class c1 = Student.class;//實際告訴我們?nèi)魏我粋€類都有一個隱含的靜態(tài)成員變量class(知道類名時用)
Class c2 = stu.getClass();//已知該類的對象通過getClass方法(知道對象時用) Student是一個類永丝,stu是它的對象,通過 stu.getClass() 就獲取到了 Car 這個類的 Class 對象
Class c3 = Class.forName("類的全名");//會有一個ClassNotFoundException異常
有時候箭养,我們沒有辦法創(chuàng)建一個類的實例慕嚷,甚至沒有辦法用 Student.class 這樣的方式去獲取一個類的 Class 對象。這在 Android 開發(fā)領(lǐng)域很常見,因為某種目的喝检,Android 工程師把一些類加上了 @hide 注解嗅辣,所示這些類就沒有出現(xiàn)在 SDK 當(dāng)中,Java 給我們提供了 Class.forName() 這個方法挠说。
只要給這個方法中傳入一個類的全限定名稱就好了澡谭,那么它就會到 Java 虛擬機(jī)中去尋找這個類有沒有被加載。
當(dāng)我們執(zhí)行System.out.println(c1==c2);語句损俭,結(jié)果返回的是true蛙奖,這是為什么呢?原因是不管c1還是c2都代表了Student類的類類型杆兵,一個類可能是Class類的一個實例對象外永。

我們完全可以通過類的類類型創(chuàng)建該類的對象實例,即通過c1或c2創(chuàng)建Student的實例拧咳。
Student stu = (Student)c1.newInstance();//前提是必須要有無參的構(gòu)造方法,因為該語句會去調(diào)用其無參構(gòu)造方法囚灼。該語句會拋出異常骆膝。

1.Class clazz = xxx.class 只會觸發(fā)類的加載,不會觸發(fā)初始化
2.Class clazz = new xxx().getClass()

  1. Class.forName(“全限定名稱com.shadow.Hello”) 2,3方法都同時觸發(fā)類的加載和初始化灶体。阅签。 全限定名稱,它包括包名+類名

動態(tài)加載類和靜態(tài)加載類

①.編譯時加載類是靜態(tài)加載類
new 創(chuàng)建對象是靜態(tài)加載類蝎抽,在編譯時刻就需要加載所有可用使用到的類政钟,如果有一個用不了,那么整個文件都無法通過編譯
②.運行時加載類是動態(tài)加載類
Class c = Class.forName("類的全名")樟结,不僅表示了類的類型养交,還表示了動態(tài)加載類,編譯不會報錯瓢宦,在運行時才會加載碎连,使用接口標(biāo)準(zhǔn)能更方便動態(tài)加載類的實現(xiàn)。
功能性的類盡量使用動態(tài)加載驮履,而不用靜態(tài)加載鱼辙。
很多軟件比如QQ,360的在線升級,并不需要重新編譯文件玫镐,只是動態(tài)的加載新的東西

動態(tài)加載小例子

需求:在不知道的情況下倒戏,可能只加載World也有可能只加載Excel

package shadow.android.com.lib.reflected;

/**
 * Author : shadow
 * Desc : 動態(tài)加載類的基類
 * Date :2018/11/2/002
 */
public interface OfficeBase {
    public void start();
}

//==================================

package shadow.android.com.lib.reflected;

/**
 * Author : shadow
 * Desc :
 * Date :2018/11/2/002
 */
public class World implements OfficeBase {
    @Override
    public void start() {
        System.out.println("hello shadow,this is world");
    }
}

//============================

package shadow.android.com.lib.reflected;

/**
 * Author : shadow
 * Desc :
 * Date :2018/11/2/002
 */
public class Excel implements OfficeBase {
    @Override
    public void start() {
        System.out.println("hello shadow恐似,this is excel6捧巍!!");
    }
}

靜態(tài)加載如下:靜態(tài)加載要求編譯時期World或者Excel必須都在葱椭,然后根據(jù)情況判斷來決定是否要使用捂寿,不然編譯時期就會出錯

package shadow.android.com.lib.reflected;

/**
 * Author : shadow
 * Desc :靜態(tài)加載測試
 * Date :2018/11/2/002
 */
public class StaticLoaderTest {
    public static void main(String[] args) {
        if ("world".equals(args[0])) {
            World world = new World();
            world.start();
        }

        if ("excel".equals(args[0])) {
            Excel excel = new Excel();
            excel.start();
        }
    }
}

動態(tài)加載如下:不要求在編譯時刻,World和Excel同時存在孵运,只需要在加載的時候秦陋,根據(jù)需要去加載需要Class,如果加載不到治笨,會拋出ClassNotFoundException

package shadow.android.com.lib.reflected;

/**
 * Author : shadow
 * Desc :動態(tài)加載測試
 * Date :2018/11/2/002
 */
public class DynamicLoaderTest {
    public static void main(String[] args){
        try {
            //動態(tài)加載類驳概,
           // Class clazz = Class.forName(args[0]);
            Class clazz = Class.forName("shadow.android.com.lib.reflected.World");
            //由類類型,創(chuàng)建類的實例
            OfficeBase officeBase = (OfficeBase) clazz.newInstance();
            //擴(kuò)展類
            officeBase.start();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

動態(tài)加載類測試.png

class對象的操作

如果你想得到一個類的信息旷赖,首先就要獲取該類的類類型顺又。
拿到class對象之后,可以操作一下幾類對象等孵,比如類的實現(xiàn)接口稚照,類的變量,類的方法俯萌,類的構(gòu)造器等果录,class類提供了對應(yīng)的方法來訪問
getName() 返回類類型的名字
getSuperClass() 返回繼承的父類對象
getInterfaces() — 返回當(dāng)前類實現(xiàn)的所有接口(不包括從父類繼承來的)
getClasses() — 返回當(dāng)前類和從父類繼承來的public內(nèi)部類
getDeclaredClasses() — 返回當(dāng)前類的所有內(nèi)部類(包括private類型,但是不包括從父類繼承來的)
getConstructors() — 返回當(dāng)前類所有的public構(gòu)造器
getDeclaredConstructors() — 返回當(dāng)前類所有的構(gòu)造器(包括private類型)
getConstructor(Class<?>… parameterTypes) — 根據(jù)參數(shù)咐熙,返回最匹配的構(gòu)造器對象
getMethods() — 返回當(dāng)前類和從父類繼承來的所有public方法
getDeclaredMethods() — 返回當(dāng)前類所有的Method方法(包括private類型)
getDeclaredMethod(String name, Class<?>… parameterTypes) — 根據(jù)參數(shù)弱恒,返回最匹配的方法
getFields() — 返回當(dāng)前類和從父類繼承來的public字段
getDeclaredFields() — 返回當(dāng)前類定義的所有字段(包括private)
getDeclaredField(String name) —返回當(dāng)前類定義的字段通過參數(shù)
Class類api 有很多,需要用時可以查看api文檔


1.如何獲取某個方法
   方法的名稱和方法的參數(shù)列表才能唯一決定某個方法
   Method m = c.getDeclaredMethod("方法名"棋恼,可變參數(shù)列表(參數(shù)類型.class))
2.方法的反射操作
   m.invoke(對象返弹,參數(shù)列表)
   方法如果沒有返回值,返回null爪飘,如果有返回值返回Object類型义起,然后再強(qiáng)制類型轉(zhuǎn)換為原函數(shù)的返回值類型

通過反射,了解泛型只在編譯時期有效


ArrayList list1 =newArrayList();
ArrayList<String> list2 =newArrayList<String>();

Class c1 = list1.getClass();
Class c2 = list2.getClass();

System.out.println(c1==c2);//結(jié)果為true悦施,為什么并扇??

結(jié)果分析:因為反射的操作都是編譯之后的操作抡诞,也就是運行時的操作穷蛹,c1==c2返回true,說明編譯之后集合的泛型是去泛型化的昼汗。
那么我們就可以理解為肴熏,Java集合中的泛型,是用于防止錯誤類型元素輸入的顷窒,比如在list2中我們add一個int蛙吏,add(10)就會編譯報錯源哩,那么這個泛型就可以只在編譯階段有效,通過了編譯階段鸦做,泛型就不存在了励烦。可以驗證泼诱,我們繞過編譯坛掠,用反射動態(tài)的在list2中add一個int是可以成功的,只是這時因為list2中存儲了多個不同類型的數(shù)據(jù)(String型治筒,和int型)屉栓,就不能用for-each來遍歷了,會拋出類型轉(zhuǎn)換錯誤異常ClassCastException耸袜。

例子實現(xiàn)

需求:現(xiàn)在有個Apple類友多,它繼承于Fruit類,F(xiàn)ruit有一個私有方法seal 參數(shù)是一個float類型, 現(xiàn)在要求我們通過反射來調(diào)用該私有方法

Fruit.class

public class Fruit {
    private int price;

    public Fruit(int price) {
        this.price = price;
    }

    private void sale(int price) {
        System.out.println("hello shadow ,fruit " + price);
    }
}

Apple.class

package shadow.android.com.lib.reflected;
public class Apple extends Fruit{
    public Apple(int price) {
        super(price);
    }
}

反射類

package shadow.android.com.lib.reflected;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Author : shadow
 * Desc :
 * Date :2018/11/2/002
 */
public class TestReflected {
    public static void main(String[] args) {
        invokeFruitSale();
    }

    private static void invokeFruitSale() {
        try {
            //獲取Apple類
            Class clazz = Class.forName("shadow.android.com.lib.reflected.Apple");
            //獲取Apple的直接父類Fruit
            Class fruitClass = clazz.getSuperclass();

            //獲取fruit的私有方法
            Method saleMethod = fruitClass.getDeclaredMethod("sale", int.class);
            saleMethod.setAccessible(true);

            //獲取父類的私有構(gòu)造器
            Constructor constructor = fruitClass.getDeclaredConstructor(int.class);
            //設(shè)置私有可訪問
            constructor.setAccessible(true);
            //通過私有構(gòu)造器新建Fruit對象
            Fruit fruit = (Fruit) constructor.newInstance(0);


            //調(diào)用方法
            saleMethod.invoke(fruit, 100);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

例子實現(xiàn)2

這次我們在Fruit類中新建一個Size類堤框,然后新增一個final的Size常量域滥,我們需要利用反射對其進(jìn)行修改(正常final常量初始化之后是不能夠被修改的,但是利用反射能夠做到-蜈抓。-)

fruit類

package shadow.android.com.lib.reflected;

/**
 * Author : shadow
 * Desc :
 * Date :2018/11/2/002
 */
public class Fruit {
    private int price;
    private final Size size = new Size(50);

    public Fruit(int price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "fruit size is : " + size;
    }

    private void sale(int price) {
        System.out.println("hello shadow ,fruit " + price);
    }

    public static class Size {
        private int count;

        public Size(int count) {
            this.count = count;
        }

        @Override
        public String toString() {
            return "size = " + count;
        }
    }
}

執(zhí)行反射的類

   private static void modifyFruitSize() {
        try {
            Class clazz = Class.forName("shadow.android.com.lib.reflected.Apple");
            Class fruitClass = clazz.getSuperclass();
            Constructor constructor = fruitClass.getDeclaredConstructor(int.class);
            constructor.setAccessible(true);
            Fruit fruit = (Fruit) constructor.newInstance(0);
            //修改之前打印fruit size
            System.out.println("before modify fruit size" + fruit);

            //獲取私有變量
            Field sizeField = fruitClass.getDeclaredField("size");
            sizeField.setAccessible(true);
            //我們利用反射將size改為非final類型
            Field modifierField = sizeField.getClass().getDeclaredField("modifiers");
            modifierField.setAccessible(true);
            //修改類型
            int modifiers = sizeField.getModifiers() & ~Modifier.FINAL;
            modifierField.set(sizeField, modifiers);
            //設(shè)置新的size
            Fruit.Size size = new Fruit.Size(500);
            sizeField.set(fruit, size);
            System.out.println("after modify fruit size" + fruit);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

例子3 Android Activity 啟動 Hook骗绕。

Android Activity 啟動 Hook

當(dāng)然關(guān)于Android Activity 啟動 Hook的技術(shù)網(wǎng)上很多,也有很多很優(yōu)秀的開源項目资昧,我在這里談這個有點 關(guān)公面前耍大刀的感覺了,但是我在這里談這個只是為了說明 利用反射 我們可以做很多事情荆忍,
所以我就找了這么一個切入點來展示反射能做什么事情格带,權(quán)當(dāng)拋磚引玉。
我們的需求是刹枉,在啟動activity時叽唱,打印一個Log日志,廢話不多說微宝,我們開始棺亭。
我們這里只Hook Activity.startActivity 這種方式的啟動, 看下android framework的相關(guān)源碼


public void startActivity(Intent intent) {
    //常用的activity.startActivity方法
    this.startActivity(intent, null);
}
//...

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
     if (options != null) {
        startActivityForResult(intent, -1, options);
     } else {
         // Note we want to go through this call for compatibility with
         // applications that may have overridden the method.
         startActivityForResult(intent, -1);
     }
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
     if (mParent == null) {
         options = transferSpringboardActivityOptions(options);
         Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
         //...
     }
     //...
}

private Instrumentation mInstrumentation;
我們看到activity.startActivity方法,最終去執(zhí)行啟動操作會用到mInstrumentation這個私有成員變量蟋软,所以自然想到它是一個很好的Hook點镶摘,分下面三步來走

第一步,先獲取到該Activity的mInstrumentation
第二步岳守,新建一個新的Instrumentation類凄敢,重寫execStartActivity方法,在執(zhí)行父類的方法之前加入我們需要的Log日志
第三步湿痢,將我們新建的新的Instrumentation對象涝缝,設(shè)置給activity
第一步


public static void hook(Activity activity) {
    try {
        Field instrumentationField = Activity.class.getDeclaredField("mInstrumentation");
        instrumentationField.setAccessible(true);
        //...
    }
}

第二步


public class HookInstrumention extends Instrumentation{

    private Instrumentation mTarget;

    public HookInstrumention(Instrumentation target) {
        this.mTarget = target;
    }

    public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
                                  Intent intent, int requestCode, Bundle options) {
        L.d("before start activity!");
        Class superClass = Instrumentation.class;
        try {
            Method method = superClass.getDeclaredMethod("execStartActivity",
                    Context.class, IBinder.class, IBinder.class, Activity.class,
                    Intent.class, int.class, Bundle.class);
            method.setAccessible(true);
            return (ActivityResult) method.invoke(this.mTarget, who, contextThread, token, target, intent, requestCode, options);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
}

第三步


public static void hook(Activity activity) {
    try {
        Field instrumentationField = Activity.class.getDeclaredField("mInstrumentation");
        instrumentationField.setAccessible(true);
        Instrumentation instrumentation = (Instrumentation) instrumentationField.get(activity);
        HookInstrumention hookInstrumention = new HookInstrumention(instrumentation);
        instrumentationField.set(activity, hookInstrumention);
    } catch (NoSuchFieldException e) {
         e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

//測試一下:
HookUtil.hook(this);
startActivity(new Intent(MainActivity.this, SecondActivity.class));

//查看log
08-27 14:43:33.391 10298-10298/com.aliouswang.practice.olympic E/hook: before start activity!
08-27 14:43:33.392 10298-10298/com.aliouswang.practice.olympic I/Timeline: Timeline: Activity_launch_request time:427958941 intent:Intent { cmp=com.aliouswang.practice.olympic/.SecondActivity }
可以看到我們在Activity 啟動之前,成功的打印了一條日志!拒逮!

總結(jié)反射

Java 中的反射是非常規(guī)編碼方式罐氨。
Java 反射機(jī)制的操作入口是獲取 Class 文件。 有 Class.forName()滩援、 .class 和 Object.getClass() 3 種栅隐。
獲取 Class 對象后還不夠,需要獲取它的 Members狠怨,包含 Field约啊、Method、Constructor佣赖。
Field 操作主要涉及到類別的獲取恰矩,及數(shù)值的讀取與賦值。
Method 算是反射機(jī)制最核心的內(nèi)容憎蛤,通常的反射都是為了調(diào)用某個 Method 的 invoke() 方法外傅。
通過 Class.newInstance() 和 Constructor.newInstance() 都可以創(chuàng)建類的對象實例,但推薦后者俩檬。因為它適應(yīng)于任何構(gòu)造方法萎胰,而前者只會調(diào)用可見的無參數(shù)的構(gòu)造方法。
數(shù)組和枚舉可以被看成普通的 Class 對待棚辽。

凡事有得必有失技竟,反射也有它的缺點,反射的缺點主要有2點屈藐。

我們通過反射獲得了靈活性榔组,同時也要付出代價,我們會失去編譯器優(yōu)化我們代碼的機(jī)會联逻,這樣我們的代碼執(zhí)行效率會低一些搓扯,但是隨著JDK版本的不斷升級,性能差距在不斷的縮小包归。
反射打破了我們代碼的封裝性锨推,增加了維護(hù)成本。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末公壤,一起剝皮案震驚了整個濱河市换可,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厦幅,老刑警劉巖锦担,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異慨削,居然都是意外死亡洞渔,警方通過查閱死者的電腦和手機(jī)套媚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磁椒,“玉大人堤瘤,你說我怎么就攤上這事〗郏” “怎么了本辐?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長医增。 經(jīng)常有香客問我慎皱,道長,這世上最難降的妖魔是什么叶骨? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任茫多,我火速辦了婚禮,結(jié)果婚禮上忽刽,老公的妹妹穿的比我還像新娘天揖。我一直安慰自己,他們只是感情好跪帝,可當(dāng)我...
    茶點故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布今膊。 她就那樣靜靜地躺著,像睡著了一般伞剑。 火紅的嫁衣襯著肌膚如雪斑唬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天黎泣,我揣著相機(jī)與錄音赖钞,去河邊找鬼。 笑死聘裁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的弓千。 我是一名探鬼主播衡便,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洋访!你這毒婦竟也來了镣陕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤姻政,失蹤者是張志新(化名)和其女友劉穎呆抑,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汁展,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡鹊碍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年厌殉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侈咕。...
    茶點故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡公罕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耀销,到底是詐尸還是另有隱情楼眷,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布熊尉,位于F島的核電站罐柳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏狰住。R本人自食惡果不足惜张吉,卻給世界環(huán)境...
    茶點故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望转晰。 院中可真熱鬧芦拿,春花似錦、人聲如沸查邢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扰藕。三九已至缓苛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間邓深,已是汗流浹背未桥。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留芥备,地道東北人冬耿。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像萌壳,于是被迫代替她去往敵國和親亦镶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 廢話不多說袱瓮,自己進(jìn)入今天的主題 1缤骨、面向?qū)ο蟮奶卣饔心男┓矫妫?答:面向?qū)ο蟮奶卣髦饕幸韵聨讉€方面: - 抽象:...
    傳奇內(nèi)服號閱讀 2,343評論 1 31
  • 面試必背 會舍棄、總結(jié)概括——根據(jù)我這些年面試和看面試題搜集過來的知識點匯總而來 建議根據(jù)我的寫的面試應(yīng)對思路中的...
    luoyangzk閱讀 6,747評論 6 173
  • 1.沒有兩個人是一樣的No two persons are the same. 2.一個人不能控制另外一個人One...
    米粒2020閱讀 243評論 0 0
  • 用的是早晚牙膏尺借,晚上看的是姜文導(dǎo)的陽光燦爛的日子绊起,王朔飾演的小壞蛋沒看著,沒把牙杯里晚上用的牙膏換過來就覺得晚上沒...
    gglove閱讀 288評論 0 0
  • 今天第四次寫手帳 比較簡單粗暴燎斩。虱歪。蜂绎。 因為今天要把落下的作業(yè)都補(bǔ)完 明天要去臥佛寺 早上5:30起來 好吧我很期待...
    小太陽Monica閱讀 475評論 4 3