Java泛型的理解與使用

1.泛型簡介

  • 問題:在獲取用戶信息的API中,后臺給我們返回一個這樣形式的json字符串。

    {
        "meta": {
            "code": 0,
            "message": "ok"
        },
        "data": {
            "nick_name": "hellokitty",
            "cellphone": "18301824843",
        }
    }
    

    我們用fastJson解析上述json字符串時候,該怎么處理?
    ,我們是不是就會寫這樣一個類。

    public class User {
    
    
        private Meta meta;
        private Data data;
    
        public Meta getMeta() {
            return meta;
        }
    
        public void setMeta(Meta meta) {
            this.meta = meta;
        }
    
        public Data getData() {
            return data;
        }
    
        public void setData(Data data) {
            this.data = data;
        }
    
        static class Meta
        {
            private String code;
            private String message;
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }
    
            public String getMessage() {
                return message;
            }
    
            public void setMessage(String message) {
                this.message = message;
            }
        }
    
        static class Data
        {
    
            private String nick_name;
            private String cellphone;
    
            public String getNick_name() {
                return nick_name;
            }
    
            public void setNick_name(String nick_name) {
                this.nick_name = nick_name;
            }
    
            public String getCellphone() {
                return cellphone;
            }
    
            public void setCellphone(String cellphone) {
                this.cellphone = cellphone;
            }
        }
    }
    

    然后調用fastjason的JSON.parseObject(msg,User.class)進行解析。

    而如果拉取設備列表API返回的數據格式是這樣的一個形式,我們該怎么處理?

    {
        "meta": {
            "code": 0,
            "message": "ok"
        },
        "data": [
            {
                "device_id": "4acb634aaf5711e8b290000c29c27f42",
                "role": 1,
                "device_alias": "hellokitty",
                "created_at": "2018-09-04T10:55:57"
            },
            {
                "device_id": "4acb634aaf5711e8b290000c29c27f42",
                "role": 1,
                "device_alias": "hellokitty",
                "created_at": "2018-09-04T10:55:57"
            }
        ]
    }
    

    是不是我們仍然要再寫一個解析類來解析這個設備列表類。

        public class DeviceList {
    
        private Meta meta;
        private List<Device> data;
    
        public Meta getMeta() {
            return meta;
        }
    
        public void setMeta(Meta meta) {
            this.meta = meta;
        }
    
        public List<Device> getData() {
            return data;
        }
    
        public void setData(List<Device> data) {
            this.data = data;
        }
    
        static class Meta
        {
            private String code;
            private String message;
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }
    
            public String getMessage() {
                return message;
            }
    
            public void setMessage(String message) {
                this.message = message;
            }
        }
    
        static class Device
        {
            @Override
            public String toString() {
                return "Device{" +
                        "device_id='" + device_id + '\'' +
                        ", role=" + role +
                        ", device_alias='" + device_alias + '\'' +
                        ", created_at='" + created_at + '\'' +
                        '}';
            }
    
            private String device_id;
            private int role;
            private String device_alias;
            private String created_at;
    
            public String getDevice_id() {
                return device_id;
            }
    
            public void setDevice_id(String device_id) {
                this.device_id = device_id;
            }
    
            public int getRole() {
                return role;
            }
    
            public void setRole(int role) {
                this.role = role;
            }
    
            public String getDevice_alias() {
                return device_alias;
            }
    
            public void setDevice_alias(String device_alias) {
                this.device_alias = device_alias;
            }
    
            public String getCreated_at() {
                return created_at;
            }
    
            public void setCreated_at(String created_at) {
                this.created_at = created_at;
            }
        }
    }
    
    

    如果每次都這樣的話,會不會要創建很多很相像的類,他們只是里面部分變量不同,其他的部分都相同。

    再舉一個栗子:
    如果我們想要產生多個對象,每個對象的邏輯完全一樣,只是對象內的成員變量的類型不同,那我們如何去做?
    在下面我們創建了兩個類,只是data的變量類型不同,是不是也可以達到我們剛才的要求。

     static class MyClass1
    {
        public MyClass1() {
        }
    
        private String data;
    
        public MyClass1(String data) {
            this.data = data;
        }
    
        public String getData() {
            return data;
        }
    
        public void setData(String data) {
            this.data = data;
        }
    }
    
    static class MyClass2
    {
        public MyClass2() {
        }
    
        private int data;
    
        public MyClass2(int data) {
            this.data = data;
        }
    
        public int getData() {
            return data;
        }
    
        public void setData(int data) {
            this.data = data;
        }
    }
    

    打印結果:

        MyClass1 myClass1 = new MyClass1();
        myClass1.setData("Cyy");
        MyClass2 myClass2 = new MyClass2();
        myClass2.setData(10);
        System.out.println(myClass1.getData());
        System.out.println(myClass2.getData());
    

    輸出:

    Cyy
    10
    

    但是如果我們還想要這樣一個對象呢,那我們是不是還要繼續去創建這樣的對象,那如果我還要10個這個的對象呢,那我們是不是就要創建十個。這樣明顯是很笨重的一種解決方案。

    那我們現在思考,如果我們用Object來代替呢?

        static class MyClass1
        {
            public MyClass1() {
            }
    
            private Object data;
    
            public MyClass1(Object data) {
                this.data = data;
            }
    
            public Object getData() {
                return data;
            }
    
            public void setData(Object data) {
                this.data = data;
            }
        }
    

    打印輸出:

       MyClass1 myClass1 = new MyClass1();
        myClass1.setData("Cyy");
        System.out.println((String)myClass1.getData());
        MyClass1 myClass2 = new MyClass1();
        myClass2.setData(10);
        System.out.println((int)myClass2.getData());
    
        ```
    輸出結果:
    
    
      Cyy
      10
    
    呀~看上去好像完美解決了,不用創建多個類,就可以實現剛才需要功能,好像很完美,現在讓他變成不完美,現在我們讓他這樣打印出來.
    
       MyClass1 myClass2 = new MyClass1();
          myClass2.setData(10);
          System.out.println((String)myClass2.getData());
    
    注意我們給他的是整型,但是打印時候我們給他的強轉類型是String,現在看下會發生什么問題。
    
      Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
      at SecDemo.main(SecDemo.java:13)
    
    它提示了,類型轉換異常。
    
     總結
            
        方案(一) :
            
        方法: 創建多個類文件,給每個類中的成員變量設置指定的數據類型。
            
        缺點: 導致類的膨脹,重用性太差
            
        方案(二) :
            
        方法: 創建一個類文件,給這個類中的成員變量設置Object數據類型
            
        缺點:編譯的時候正常,但運行時候可能會報錯.
            
        泛型類就能很好的解決以上兩個問題。
    
    

2.泛型類

  • 泛型是JDK1.5引入的新特性,也是最重要的一個特性。

  • 泛型可以在編譯的時候檢查類型安全,并且所有的強制轉換都是自動和隱式的。

  • 泛型的原理就是類型的參數化,即把類型看做參數,也就是說把所要操作的數據類型看做參數,就像方法的形式參數是運行時傳遞的值一樣。

  • 簡單的說,類型變量扮演的角色如同一個參數,它提供給編譯器用來類型檢查的信息。

  • 泛型可以提高代碼的擴展性和重用性
    **

    如果我們將剛才的類改成泛型類是什么樣子的呢?

    static class MyClass1<T>
    {
        public MyClass1() {
        }
    
        private T data;
    
        public MyClass1(T data) {
            this.data = data;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    我們發現在類的開頭多了個<T>,這個就代表著傳入進來的參數,他可以是整型,可以是字符串類型,只要你傳進來了那么后續的get,set方法就全部都是這種類型了。他就相當于一個操作的參數。好的現在我們試一下。

    打印輸出:

    MyClass1 myClass1 = new MyClass1<String>();
        myClass1.setData("Cyy");
        System.out.println(myClass1.getData());
        MyClass1 myClass2 = new MyClass1<Integer>();
        myClass2.setData(10);
        System.out.println(myClass2.getData());
    

    輸出:

    Cyy
    10
    
    

    有沒有發現,我們不用進行強制類型轉換仍然能輸出正確的數值。
    注意下,當我們new MyClass1<String>()傳的是String那么我們類里面的所有T就都是String類型了。

    總結:

    泛型類使用優點:

    • 防止類膨脹

    • 不再手動進行類型轉換

    泛型類的使用
    1. 泛型的類型參數可以是泛型類
    static class MyClass1<T1>
        {
            public MyClass1() {
            }
    
            private T1 data1;
    
            public T1 getData1() {
                return data1;
            }
    
            public void setData1(T1 data1) {
                this.data1 = data1;
            }
        }
    
        static class Student
        {
            private String name;
    
            public Student(String name) {
                this.name = name;
            }
    
            @Override
            public String toString() {
                return "Student{" +
                        "name='" + name + '\'' +
                        '}';
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
        }
        
    

    使用:

     MyClass1<MyClass1<Student>> myClass1MyClass1 = new  MyClass1<MyClass1<Student>>();
            MyClass1<Student> myClass1 = new MyClass1<Student>();
            myClass1.setData1(new Student("cyy"));
            myClass1MyClass1.setData1(myClass1);
            System.out.println(myClass1MyClass1.getData1().getData1().toString());
    

    輸出:

    Student{name='cyy'}
    
    1. 泛型類可以同時設置多個類型參數
    static class MyClass1<T1,T2>
        {
            public MyClass1() {
            }
    
            private T1 data1;
            private T2 data2;
    
            public T2 getData2() {
                return data2;
            }
    
            public void setData2(T2 data2) {
                this.data2 = data2;
            }
    
            public T1 getData1() {
                return data1;
            }
    
            public void setData1(T1 data1) {
                this.data1 = data1;
            }
        }
    

    使用:

    MyClass1<String,Integer> myClass1 = new MyClass1<String,Integer>();
            myClass1.setData1("Cyy");
            myClass1.setData2(25);
            System.out.println(myClass1.getData1());
            System.out.println(myClass1.getData2());
    

    輸出:

    Cyy
    25
    
    1. 泛型類可以繼承泛型類
    class SuperClass<T1>
        {
            private T1 var1;
    
            public SuperClass(T1 var1) {
                this.var1 = var1;
            }
    
            public T1 show1()
            {
                return var1;
            }
        }
    
        class SubClass<T1,T2> extends SuperClass<T1>
        {
            private T2 var2;
    
            public SubClass(T1 var1, T2 var2) {
                super(var1);
                this.var2 = var2;
            }
    
            @Override
            public T1 show1() {
                return super.show1();
            }
        }
    

    使用:

        SubClass<String,Integer> subClass = new SubClass<>("cyy",25);
        System.out.println(subClass.show1());
    

    輸出:

    cyy
    
    
    1. 泛型類可以實現泛型接口
     interface IInfo<T2>
        {
            public void show2(T2 var3);
        }
      static class SubClass<T1,T2> extends SuperClass<T1> implements IInfo<T2>
        {
            private T2 var2;
    
            public SubClass(T1 var1, T2 var2) {
                super(var1);
                this.var2 = var2;
            }
    
            @Override
            public T1 show1() {
                return super.show1();
            }
    
            @Override
            public void show2(T2 var3) {
    
                System.out.println(var3);
                System.out.println(var2);
            }
        }
    

    使用:

     SubClass<String,Integer> subClass = new SubClass<>("cyy",25);
            subClass.show2(100);
            System.out.println(subClass.show1());
    

    輸出:

    100
    25
    cyy
    

    注:不可以進行泛型變量之間的運算,因為泛型變量在編譯期間會進行類型擦除,全部變成Object,比如Object+Object就不知道是什么類型了,所以這點很重要。

    OK,現在我們可以回到最初那個問題上了,我們可以利用泛型定義一個CommResult類。

    public class CommResult <T> {
    
        private Meta meta;
        private T data;
    
        public Meta getMeta() {
            return meta;
        }
    
        public void setMeta(Meta meta) {
            this.meta = meta;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        static class Meta
        {
            private String code;
            private String message;
    
            public String getCode() {
                return code;
            }
    
            public void setCode(String code) {
                this.code = code;
            }
    
            public String getMessage() {
                return message;
            }
    
            public void setMessage(String message) {
                this.message = message;
            }
        }
    }
    

    然后使用的時候我們可以這樣:

    JSON.parseObject(msg,CommResult<User>)JSON.parseObject(msg,CommResult<List<Device>>)

    這樣就完美避免了創建多個結構一樣,但是只有里面部分變量不一致的類了。

    3.限制泛型可用類型

    在定義泛型類別時,默認在實例化泛型類的時候可以使用任何類型,但是如果想要限制使用泛型時,只能用某個特定類型或者是其子類型才能實例化該類型時,可以在定義類型時,使用extends關鍵字指定這個類型必須是繼承某個類,或者實現某個接口。
    當沒有指定泛型繼承的類型或接口時,默認使用extends Object,所以默認情況下,可以使用任何類型作為參數。

     class GenericClass<T extends Animal>
        {
            private T data;
    
            public GenericClass(T data)
            {
                this.data = data;
            }
    
            public T getData() {
                return data;
            }
    
            public void setData(T data) {
                this.data = data;
            }
        }
    
        abstract class Animal
        {
            public abstract void eat();
        }
    
        class Dog extends Animal
        {
            @Override
            public void eat() {
    
                System.out.println("啃骨頭");
            }
        }
    
        class Cat extends Animal
        {
    
            @Override
            public void eat() {
    
                System.out.println("吃魚肉");
            }
        }
    

    現在我們看下,如果我在泛型類里面傳個String類型的參數,看他會報什么?
    Type parameter 'java.lang.String' is not within its bound; should extend 'Test.Animal

    他說String不是Animal子類,不行吧。

    如果我們換成這樣就可以了。

    GenericClass<Dog> genericClass = new GenericClass<>(new Dog());
            genericClass.getData().eat();
            GenericClass<Cat> genericClasscat = new GenericClass<>(new Cat());
            genericClasscat.getData().eat();
    

    如果換成接口呢?

    class GenericClass<T implements eat>
    {
        private T data;
    
        public GenericClass(T data)
        {
            this.data = data;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    這樣寫對不對,這樣寫是不對的,編譯器會報錯的,因為不管是接口還是類,都要用extends。所以換成接口也要寫成這樣就可以了。

    class Cat implements eat
    {
    
        @Override
        public void eat() {
    
            System.out.println("吃魚肉");
        }
    }
    
    class Dog implements eat
    {
    
        @Override
        public void eat() {
    
            System.out.println("啃骨頭");
        }
    }
    
    interface eat
    {
        public abstract void eat();
    }
    
    class GenericClass<T extends eat>
    {
        private T data;
    
        public GenericClass(T data)
        {
            this.data = data;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    4.類型通配聲明

    同一泛型類,如果實例化時給定的實際類型不同,則這些實例的類型是不兼容的,不能相互賦值。如:

    Generic<Boolean> f1 = new Generic<Booleab>();
    Generic<integer> f2 = new Generic<integer>();
    f1 = f2;//發生編譯錯誤
    Generic<Object> f = f1 ;//f1和f類型并不兼容,發生編譯錯誤
    f = f2;//f2和f類型同樣不兼容,也會發生編譯錯誤。
    

    泛型類實例之間的不兼容性會帶來使用的不便。我們可以使用泛型通配符(?)生命泛型類的變量就可以解決這個問題。

    泛型通配的使用方式

    • "?" 代表一個類型。
    Generic<Boolean> f1 = new Generic<Booleab>();
    
    Generic<?> f= f1;
    
    
    • 和限制泛型的上線相似,同樣可以使用extends關鍵字限定通配符匹配類型的上線:
    Generic<Dog> f1 = new Generic<Dog>();
    
    Generic<? extends Animal> f= f1;
    
    • 還可以使用super關鍵詞將通配符匹配類型限定為某個類型及其父類型
    Generic<Animal> f1 = new Generic<Animal>();
    
    Generic<? super Dog> f= f1;
    

    現在要在這里特別說下兩個限定通配符

    • extends 上邊界限定通配符
    舉個例子一看就懂了,<? extends Animal> , 那這里的`?`就必須是Animal的子類或它自己。
    
    • super 下邊界限定通配符
    舉個例子一看就懂了,<? super Dog> , 那這里的`?`就必須是Dog的父類或它自己。
    

    5.泛型方法使用

    不僅類可以聲明泛型,類中的方法也可以聲明僅用于自身的泛型,這種方法叫做泛型方法。其定義格式為:

    訪問修飾符<泛型列表> 返回類型 方法名(參數列表) 
    {
        實現代碼
    }
    

    在泛型列表中聲明的泛型,可用于該方法的返回類型聲明,參數類型聲明和方法代碼中的局部變量的類型聲明。

    類中其他方法不能使用當前方法聲明的泛型。

    注:是否擁有泛型方法,與其所在的類是否是泛型沒有關系。要定義泛型方法,秩序將泛型參數列表置于返回值之前。

    什么時候使用泛型方法,而不是泛型類呢?

    • 添加類型約束只作用于一個方法的多個參數之間,而不涉及類中的其他方法時。

    • 施加類型約束的方法為靜態方法,只能將其定義為泛型方法,因為靜態方法不能使用其所在類的類型參數。

    再舉個代碼的例子:

    現在我們先定義一個泛型類:

    public class Demo1 {
    
       public static void main(String[] args)
       {
    
            GenericClassOne<String> genericClassOne = new GenericClassOne<>();
            genericClassOne.printlinT(10);
        }
    
    }
    
    
    class GenericClassOne<T>
    {
        public void printlinT(T content)
        {
            System.out.println(content);
        }
    }
    

    如果我們這么寫,肯定編譯就報錯誤了吧,因為我們上面定義的是String類型,但是我們傳給他的是int型的。那如果這樣的話,這個方法是不是就有局限性了。

    那如果我們現在使用泛型方法呢?該怎么寫?

        public class Demo1 {
    
        public static void main(String[] args)
        {
    
            GenericClassOne genericClassOne = new GenericClassOne();
            genericClassOne.printlinT(10);
            genericClassOne.printlinT("cyy");
            genericClassOne.printlinT(12.5);
        }
    
    }
    
    
    class GenericClassOne<T>
    {
        //泛型方法,類型定義寫在返回值之前了
        public <T> void printlinT(T content)
        {
            System.out.println(content);
        }
    }
    

    這下不會再報編譯錯誤了,現在看下打印結果。

    輸出:

    10
    cyy
    12.5
    

    這樣是不是就靈活了許多啦~

    那么泛型的方法可不可以重載呀,當然可以,我們仍然可以寫成這樣。

    class GenericClassOne<T>
    {
        //泛型方法,類型定義寫在返回值之前了
        public <T> void printlinT(T content)
        {
            System.out.println(content);
        }
    
        //泛型方法,類型定義寫在返回值之前了
        public <T extends Animal> void printlinT(T animal)
        {
            animal.eat();
        }
    }
    
    abstract class Animal
    {
        public abstract void eat();
    }
    

    因為泛型類在編譯過程中會有個擦除的工作,所以第一個printlnT(T content)中的泛型會變成object,而第二個泛型方法中的T會變成Animal。所以他的方法可以被重載。

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

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 廢話不多說,自己進入今天的主題 1、面向對象的特征有哪些方面? 答:面向對象的特征主要有以下幾個方面: - 抽象:...
    傳奇內服號閱讀 2,369評論 1 31
  • 假日的我,輕松輕松筋骨,放松放松上班的緊張節奏感,掃掃地,拖拖地板,自個兒樂樂哼哼唱唱幾句小曲,怡然自樂著,陶醉于...
    小草_d5ad閱讀 216評論 17 21
  • 我們常能聽到這樣的感嘆:“唉,都談了5年了,盡管有太多不滿意,但是我不想放棄這段感情”。 或者還有人說: “我們都...
    瑞田學習力閱讀 373評論 1 5
  • 最近發生了很多事情,感嘆“計劃趕不上變化”這句話是真理。我急需要正念來內修下自己。碰巧本周是輪到我在微信群...
    瑋葦子閱讀 160評論 0 1