摘要:對于方法,用戶一般不會去調(diào)用,相當于根據(jù)一定的規(guī)則將與對象相關(guān)的信息映射為一個數(shù)值,稱為散列值。一般在在覆蓋方法的同時也要覆蓋方法,否則將會違反的通用約定,從而導(dǎo)致該類無法與所有基于散列值的集合類結(jié)合在一起正常工作。
1. Java中如何比較兩個Long對象是否相等?
如果Long的值在[-127,128]之間,用“==”判斷是否相等是沒問題的,如果不在這個區(qū)間,是不能用“==”的,原因如下源碼解釋:
public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
如果不在[-127,128]之間,則會new一個新對象,自然“==”兩個不同的對象,其結(jié)果必然是false了。
解決辦法:
a. : 使用Long中的longValue()進行轉(zhuǎn)換
Long a = 128l; Long b = 128l; a.longValue() == b.longValue() //true
b. : Long中的equals()
public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; }2.Java中進程和線程的區(qū)別
https://blog.csdn.net/QQ1608731824/article/details/81461269
進程是資源分配的最小單位,線程是CPU調(diào)度的最小單位
地址空間和其它資源:進程間相互獨立,同一進程的各線程間共享。某進程內(nèi)的線程在其它進程不可見。
通信:進程間通信IPC,線程間可以直接讀寫進程數(shù)據(jù)段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數(shù)據(jù)的一致性。
調(diào)度和切換:線程上下文切換比進程上下文切換要快得多。
在多線程OS中,進程不是一個可執(zhí)行的實體。
線程之間如何實現(xiàn)資源共享:
將要共享的數(shù)據(jù)封裝成另外一個對象,對這個對象進行操作
將Runnable作為一個內(nèi)部類,并在外部類中定義要共享的成員變量
3. 重寫equals為什么要重寫hashcode()?對于==:如果作用于基本數(shù)據(jù)類型的變量,則直接比較其存儲的 “值”是否相等;
如果作用于引用類型的變量,則比較的是所指向的對象的地址
對于equals方法:注意:equals方法不能作用于基本數(shù)據(jù)類型的變量
如果沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址;
諸如String、Date等類對equals方法進行了重寫的話,比較的是所指向的對象的內(nèi)容。
hashCode()方法:Object類中的本地方法,也用來判斷兩個對象是否相等。
如果沒有重寫hashCode()方法,該方法返回的是對象在內(nèi)存中的地址轉(zhuǎn)換成的int值,因此,任何對象的hashCode()方法值是不相等的。
equals()方法也是判斷兩個對象是否相等,但是與hashCode()方法有區(qū)別。一般來講,equals()方法是給用戶調(diào)用的,依據(jù)情況可以選擇重寫或者不重寫。對于hashCode()方法,用戶一般不會去調(diào)用,hashCode相當于根據(jù)一定的規(guī)則將與對象相關(guān)的信息映射為一個數(shù)值,稱為散列值。一般在在覆蓋equals()方法的同時也要覆蓋hashCode()方法,否則將會違反Object hashCode的通用約定,從而導(dǎo)致該類無法與所有基于散列值的集合類結(jié)合在一起正常工作。
Object hashCode()方法的通用約定:
如果x.equals(y)返回true,那么這兩個對象的hashCode()方法必須產(chǎn)生同樣的整數(shù)結(jié)果;
如果x.equals(y)返回false,那么這兩個對象的hashCode()方法產(chǎn)生的結(jié)果也可能相等,也可能不想等;
如果兩個對象的hashCode()方法返回值不相等,則x.equals(y)一定為false
如果兩個對象的hashCode()方法返回值相等,則x.equals(y)可能為true,可能為false。
4. Java的淺拷貝和深拷貝淺拷貝:使用一個已知實例對新創(chuàng)建實例的成員變量逐個賦值,這個方式被稱為淺拷貝。
深拷貝:當一個類的拷貝構(gòu)造方法,不僅要復(fù)制對象的所有非引用成員變量值,還要為引用類型的成員變量創(chuàng)建新的實例,并且初始化為形式參數(shù)實例值。
也就是說淺拷貝只復(fù)制一個對象,傳遞引用,不能復(fù)制實例。而深拷貝對對象內(nèi)部的引用均復(fù)制,它是創(chuàng)建一個新的實例,并且復(fù)制實例。對于淺拷貝當對象的成員變量是基本數(shù)據(jù)類型時,兩個對象的成員變量已有存儲空間,賦值運算傳遞值,所以淺拷貝能夠復(fù)制實例。但是當對象的成員變量是引用數(shù)據(jù)類型時,就不能實現(xiàn)對象的復(fù)制了
5. 為什么String被設(shè)計成不可變String 構(gòu)成:
public final class String implements java.io.Serializable, Comparable, CharSequence{ /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 ...
源碼我們可以知道String底層是由char 數(shù)組構(gòu)成的,我們創(chuàng)建一個字符串對象的時候,其實是將字符串保存在char數(shù)組中,因為數(shù)組是引用對象,為了防止數(shù)組可變,jdk加了final修飾,加了final修飾的數(shù)組只是代表了引用不可變,不代表數(shù)組的內(nèi)容不可變,因此jdk為了真正防止不可變,又加了一個private修飾符。
說到String 不得不提字符串常量池,這個常量池主要存儲在方法區(qū)中,當一個字符串被創(chuàng)建的時候,首先會去常量池中查找,如果找到了就返回對改字符串的引用,如果沒找到就創(chuàng)建這個字符串并塞到常量池中。
下面代碼只會在:
String s1 ="abc"; String s2 ="abc";
試想一下如果String是可變的,當兩個引用指向指向同一個字符串時,對其中一個做修改就會影響另外一個。5.1 什么是不可變?
對于Java而言,除了基本類型(即int, long, double等),其余的都是對象。
對于何為不可變對象,《java concurrency in practice》一書給出了一個粗略的定義:對象一旦創(chuàng)建后,其狀態(tài)不可修改,則該對象為不可變對象。
一般一個對象滿足以下三點,則可以稱為是不可變對象:
其狀態(tài)不能在創(chuàng)建后再修改;
所有域都是final類型;
其構(gòu)造函數(shù)構(gòu)造對象期間,this引用沒有泄露。
這里重點說明一下第2點,一個對象其所有域都是final類型,該對象也可能是可變對象。因為final關(guān)鍵字只是限制對象的域的引用不可變,但無法限制通過該引用去修改其對應(yīng)域的內(nèi)部狀態(tài)。因此,嚴格意義上的不可變對象,其final關(guān)鍵字修飾的域應(yīng)該也是不可變對象和primitive type值。
從技術(shù)上講,不可變對象內(nèi)部域并不一定全都聲明為final類型,String類型即是如此。在String對象的內(nèi)部我們可以看到有一個名為hash的域并不是final類型,這是因為String類型惰性計算hashcode并存儲在hash域中(這是通過其他final類型域來保證每次的hashcode計算結(jié)果必定是相同的)。除此之外,String對象的不可變是由于對String類型的所有改變內(nèi)部存儲結(jié)構(gòu)的操作都會new出一個新的String對象。5.2 不可變帶來的好處(1):安全性
1、多線程安全性因為String是不可變的,因此在多線程操作下,它是安全的,我們看下如下代碼:
public String get(String str){ str +="aaa"; return str; }
試想一下如果String是可變的,那么get方法內(nèi)部改變了str的值,方法外部str也會隨之改變。
2、類加載中體現(xiàn)的安全性類加載器要用到字符串,不可變性提供了安全性,以便正確的類被加載。
譬如你想加載java.sql. Connection類,而這個值被改成了hacked.Connection,那么會對你的數(shù)據(jù)庫造成不可知的破壞。
只有當字符串是不可變的,字符串池才有可能實現(xiàn)。字符串池的實現(xiàn)可以在運行時節(jié)約很多heap空間,因為不同的字符串變量都指向池中的同一個字符串。但如果字符串是可變的,那么String interning將不能實現(xiàn)(String interning是指對不同的字符串僅僅只保存一個,即不會保存多個相同的字符串),因為這樣的話,如果變量改變了它的值,那么其它指向這個值的變量的值也會一起改變
5.4 不可變帶來的好處(3): 緩存hashcode因為字符串是不可變的,所以在它創(chuàng)建的時候hashcode就被緩存了,不需要重新計算。這就使得字符串很適合作為Map中的鍵,字符串的處理速度要快過其它的鍵對象。這就是HashMap中的鍵往往都使用字符串。我們可以看到String中有如下代碼:
private int hash;//this is used to cache hash code.
以上代碼中hash變量中就保存了一個String對象的hashcode,因為String類不可變,所以一旦對象被創(chuàng)建,該hash值也無法改變。所以,每次想要使用該對象的hashcode的時候,直接返回即可。
5.5 不可變帶來的缺點不可變對象也有一個缺點就是會制造大量垃圾,由于他們不能被重用而且對于它們的使用就是”用“然后”扔“,字符串就是一個典型的例子,它會創(chuàng)造很多的垃圾,給垃圾收集帶來很大的麻煩。當然這只是個極端的例子,合理的使用不可變對象會創(chuàng)造很大的價值。
密碼應(yīng)該存放在字符數(shù)組中而不是String中由于String在Java中是不可變的,如果你將密碼以明文的形式保存成字符串,那么它將一直留在內(nèi)存中,直到垃圾收集器把它清除。而由于字符串被放在字符串緩沖池中以方便重復(fù)使用,所以它就可能在內(nèi)存中被保留很長時間,而這將導(dǎo)致安全隱患,因為任何能夠訪問內(nèi)存(memorydump內(nèi)存轉(zhuǎn)儲)的人都能清晰的看到文本中的密碼,這也是為什么你應(yīng)該總是使用加密的形式而不是明文來保存密碼。由于字符串是不可變的,所以沒有任何方式可以修改字符串的值,因為每次修改都將產(chǎn)生新的字符串,然而如果你使用char[]來保存密碼,你仍然可以將其中所有的元素都設(shè)置為空或者零。所以將密碼保存到字符數(shù)組中很明顯的降低了密碼被竊取的風(fēng)險。當然只使用字符數(shù)組也是不夠的,為了更安全你需要將數(shù)組內(nèi)容進行轉(zhuǎn)化。建議使用哈希的或者是加密過的密碼而不是明文,然后一旦完成驗證,就將它從內(nèi)存中清除掉
6. String 字符串常量,StringBuffer 字符串變量(線程安全),StringBuilder 字符串變量(非線程安全)一旦一個string對象在內(nèi)存(堆)中被創(chuàng)建出來,他就無法被修改。特別要注意的是,String類的所有方法都沒有改變字符串本身的值,都是返回了一個新的對象。
如果你需要一個可修改的字符串,應(yīng)該使用StringBuffer或者StringBuilder。否則會有大量時間浪費在垃圾回收上,因為每次試圖修改都有新的string對象被創(chuàng)建出來。
查看API會發(fā)現(xiàn),String、StringBuffer、StringBuilder都實現(xiàn)了 CharSequence接口,雖然它們都與字符串相關(guān),但是其處理機制不同。
String:是不可改變的量,也就是創(chuàng)建后就不能在修改了。
StringBuffer:是一個可變字符串序列,它與String一樣,在內(nèi)存中保存的都是一個有序的字符串序列(char類型的數(shù)組),不同點是StringBuffer對象的值是可變的。
StringBuilder:與StringBuffer類基本相同,都是可變字符串序列,不同點是StringBuffer是線程安全的,StringBuilder是線程不安全的。 在性能方面,由于String類的操作是產(chǎn)生新的String對象,而StringBuilder和StringBuffer只是一個字符數(shù)組的擴容而已,所以String類的操作要遠慢于StringBuffer和StringBuilder。
使用String類的場景:在字符串不經(jīng)常變化的場景中可以使用String類,例如常量的聲明、少量的變量運算。共享的場合
使用StringBuffer類的場景:在頻繁進行字符串運算(如拼接、替換、刪除等),并且運行在多線程環(huán)境中,則可以考慮使用StringBuffer,例如XML解析、HTTP參數(shù)解析和封裝。
使用StringBuilder類的場景:在頻繁進行字符串運算(如拼接、替換、和刪除等),并且運行在單線程的環(huán)境中,則可以考慮使用StringBuilder,如SQL語句的拼裝、JSON封裝等。
簡要的說,String 類型和 StringBuffer 類型的主要性能區(qū)別其實在于 String 是不可變的對象, 因此在每次對 String 類型進行改變的時候其實都等同于生成了一個新的 String 對象,然后將指針指向新的 String 對象。所以經(jīng)常改變內(nèi)容的字符串最好不要用 String,因為每次生成對象都會對系統(tǒng)性能產(chǎn)生影響,特別當內(nèi)存中無引用對象多了以后,JVM 的 GC 就會開始工作,那速度是一定會相當慢的。
而如果是使用StringBuffer類則結(jié)果就不一樣了,每次結(jié)果都會對 StringBuffer 對象本身進行操作,而不是生成新的對象,再改變對象引用。所以在一般情況下我們推薦使用 StringBuffer,特別是字符串對象經(jīng)常改變的情況下。
在某些特別情況下, String 對象的字符串拼接其實是被 JVM 解釋成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度并不會比 StringBuffer 對象慢,而特別是以下的字符串對象生成中, String 效率是遠要比 StringBuffer 快的:
String S1 = "This is only a" + "simple" + "test"; StringBuffer Sb =new StringBuilder(“This is only a").append("simple").append(" test");
你會很驚訝的發(fā)現(xiàn),生成 String S1 對象的速度簡直太快了,而這個時候 StringBuffer 居然速度上根本一點都不占優(yōu)勢。其實這是 JVM 的一個把戲,在 JVM 眼里,這個
String S1 = “This is only a" + “ simple" + “test";
其實就是:String S1 = “This is only a simple test";
所以當然不需要太多的時間了。但大家這里要注意的是,如果你的字符串是來自另外的 String 對象的話,速度就沒那么快了,譬如:
String S2 = "This is only a"; String S3 = "simple"; String S4 = "test"; String S1 = S2 +S3 + S4;
這時候 JVM 會規(guī)規(guī)矩矩的按照原來的方式去做。
6.4 總結(jié)在大部分情況下 StringBuffer > String
Java.lang.StringBuffer是線程安全的可變字符序列。一個類似于 String 的字符串緩沖區(qū),但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但通過某些方法調(diào)用可以改變該序列的長度和內(nèi)容。在程序中可將字符串緩沖區(qū)安全地用于多線程。而且在必要時可以對這些方法進行同步,因此任意特定實例上的所有操作就好像是以串行順序發(fā)生的,該順序與所涉及的每個線程進行的方法調(diào)用順序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數(shù)據(jù)。每個方法都能有效地將給定的數(shù)據(jù)轉(zhuǎn)換成字符串,然后將該字符串的字符追加或插入到字符串緩沖區(qū)中。append 方法始終將這些字符添加到緩沖區(qū)的末端;而 insert 方法則在指定的點添加字符。
例如,如果 z 引用一個當前內(nèi)容是“start”的字符串緩沖區(qū)對象,則此方法調(diào)用 z.append(“l(fā)e”) 會使字符串緩沖區(qū)包含“startle”(累加);而 z.insert(4, “l(fā)e”) 將更改字符串緩沖區(qū),使之包含“starlet”。
在大部分情況下 StringBuilder > StringBuffer
java.lang.StringBuilder是一個可變的字符序列,是JAVA 5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步,所以使用場景是單線程。該類被設(shè)計用作 StringBuffer 的一個簡易替換,用在字符串緩沖區(qū)被單個線程使用的時候(這種情況很普遍)。如果可能,建議優(yōu)先采用該類,因為在大多數(shù)實現(xiàn)中,它比 StringBuffer 要快。兩者的使用方法基本相同。
7. 序列化和反序列化 7.1 什么是序列化和反序列化Java序列化是指把Java對象保存為二進制字節(jié)碼的過程,Java反序列化是指把二進制碼重新轉(zhuǎn)換成Java對象的過程。
7.2 為什么要序列化?1.java對象的生命周期要比java虛擬機短,實際應(yīng)用中希望虛擬機停止運行之后能夠持久化指定的對象,此時可以將對象序列化保存;
2.java對象通過網(wǎng)絡(luò)傳輸?shù)臅r候,因為數(shù)據(jù)只能以二進制的形式在網(wǎng)絡(luò)中進行傳輸,因此當對象通過網(wǎng)絡(luò)發(fā)送出去之前,需要先序列化為二進制數(shù)據(jù),在接收端收到二進制數(shù)據(jù)之后反序列化成二進制對象。
在序列化的時候使用默認的方式來進行序列化,這種序列化方式僅僅對對象的非transient的實例變量進行序列化,而不會序列化對象的transient的實例變量,也不會序列化靜態(tài)變量,所以我們對不想持久化的變量可以加上transient關(guān)鍵字。注意使用默認機制,在序列化對象時,不僅會序列化當前對象本身,還會對該對象引用的其它對象也進行序列化,同樣地,這些其它對象引用的另外對象也將被序列化,以此類推。所以,如果一個對象包含的成員變量是容器類對象,而這些容器所含有的元素也是容器類對象,那么這個序列化的過程就會較復(fù)雜,開銷也較大。如果需要實現(xiàn)自定義序列化和反序列化,那么需要重寫writeObject()方法和readObject()方法。在序列化過程中,如果被序列化的類中定義了writeObject 和 readObject 方法,將會使用反射的方式調(diào)用自定義的 writeObject 和 readObject 方法,進行用戶自定義的序列化和反序列化。
2.實現(xiàn)Externalizable接口也可以完成自定義序列化,必須實現(xiàn)writeExternal()方法和readExternal()方法。 7.4 Serializable 和 Externalizable 的區(qū)別Serializable既可以采用默認的序列化和反序列化方式,也可以使用用戶自定義的序列化和反序列化的方式。
Externalizable序列化,雖然Externalizable接口繼承自Serializable接口,但是需要序列化類繼承此接口的話,Serializable所有序列化機制全部失效。Externalizable序列化的過程:使用Externalizable序列化時,在進行反序列化的時候,會重新實例化一個對象,然后再將被反序列化的對象的狀態(tài)全部復(fù)制到這個新的實例化對象當中去,因此必須有一個無參構(gòu)造方法供其調(diào)用,并且權(quán)限是public。
Java序列化和反序列化本質(zhì)上是將對象信息生成一串二進制字節(jié)碼和從二進制字節(jié)碼解析的過程。序列化算法:
1)當前類的描述
2)當前類屬性的描述
3)父類描述
4)父類屬性描述
5)父類屬性值描述
6)子類屬性值描述
類描述是從下到上,類屬性描述是從上到下。8. 如何理解面向?qū)ο?/b>
面向?qū)ο蟮娜齻€特征:封裝、繼承、多態(tài)
封裝:封裝是將客觀事物抽象成類,每個類都包含自身的數(shù)據(jù)以及操作,不必需要其他的類來完成操作。類內(nèi)部的實現(xiàn)可以自由的修改;具有清晰的對外接口。良好的封裝能夠減少耦合;
繼承:繼承是從已有的類中派生出新的類稱為子類,子類繼承父類的屬性和行為,并能夠根據(jù)自己的需求擴展新的行為,提供了代碼的復(fù)用性。
多態(tài):多態(tài)允許不同類的對象對同一消息做出響應(yīng)。提供繼承關(guān)系,子類重寫父類的方法;父類的引用執(zhí)行子類的對象;在調(diào)用父類的方法是實際上表現(xiàn)的是子類的狀態(tài)。
從內(nèi)存角度考慮:
局部變量在棧內(nèi)存中存在,當for循環(huán)語句結(jié)束,那么變量會及時被gc(垃圾回收器)及時的釋放掉,不浪費空間
如果使用循環(huán)之后還想去訪問循環(huán)語句中控制那個變量,使用while循環(huán)
從應(yīng)用場景角度考慮:
如果一個需求明確循環(huán)的次數(shù),那么使用for循環(huán)(開發(fā)中使用for循環(huán)的幾率大于while循環(huán))
如果一個需求,不知道循環(huán)了多少次,使用while循環(huán)
10. Servlet的生命周期、Servlet是否線程安全在servlet容器啟動時初始化。在web.xml
servlet在第一次被訪問時初始化。即創(chuàng)建唯一的servlet實例。(單例多線程下面會說)
當有請求訪問該servlet是,servlet容器就會創(chuàng)建針對于這個請求的servletRequest于servletResponse,然后servlet的service方法被調(diào)用。當容器把servlet生成的響應(yīng)結(jié)果發(fā)送給客戶,容器就會銷毀request和response對象
容器在銷毀該實例前調(diào)用servlet的destroy方法(釋放servlet所占用的資源,如關(guān)閉流和數(shù)據(jù)庫連接),此外還會銷毀與servlet對象關(guān)聯(lián)的ServletConfig對象。
servlet類只創(chuàng)建一個實例,對于可與客戶端的并發(fā)訪問,它是線程不安全的。
servlet的處理方式是,每次訪問時重新起一線程執(zhí)行service方法。所以要想保證servlet的線程安全,不應(yīng)該在servlet中定義實例變量。
當然完全可以通過加鎖保證線程安全,但對于成千上萬的并發(fā)訪問,性能下降。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76706.html
摘要:作為面試官,我是如何甄別應(yīng)聘者的包裝程度語言和等其他語言的對比分析和主從復(fù)制的原理詳解和持久化的原理是什么面試中經(jīng)常被問到的持久化與恢復(fù)實現(xiàn)故障恢復(fù)自動化詳解哨兵技術(shù)查漏補缺最易錯過的技術(shù)要點大掃盲意外宕機不難解決,但你真的懂數(shù)據(jù)恢復(fù)嗎每秒 作為面試官,我是如何甄別應(yīng)聘者的包裝程度Go語言和Java、python等其他語言的對比分析 Redis和MySQL Redis:主從復(fù)制的原理詳...
摘要:作為面試官,我是如何甄別應(yīng)聘者的包裝程度語言和等其他語言的對比分析和主從復(fù)制的原理詳解和持久化的原理是什么面試中經(jīng)常被問到的持久化與恢復(fù)實現(xiàn)故障恢復(fù)自動化詳解哨兵技術(shù)查漏補缺最易錯過的技術(shù)要點大掃盲意外宕機不難解決,但你真的懂數(shù)據(jù)恢復(fù)嗎每秒 作為面試官,我是如何甄別應(yīng)聘者的包裝程度Go語言和Java、python等其他語言的對比分析 Redis和MySQL Redis:主從復(fù)制的原理詳...
摘要:好不容易在月號這天中午點左右接到了來自阿里的面試電話。這里會不斷收集和更新基礎(chǔ)相關(guān)的面試題,目前已收集題。面試重難點的和的打包過程多線程機制機制系統(tǒng)啟動過程,啟動過程等等掃清面試障礙最新面試經(jīng)驗分享,此為第一篇,開篇。 2016 年末,騰訊,百度,華為,搜狗和滴滴面試題匯總 2016 年未,騰訊,百度,華為,搜狗和滴滴面試題匯總 各大公司 Java 后端開發(fā)面試題總結(jié) 各大公司 Jav...
摘要:今天整理了一下近大半年以來的一些文章,和我的預(yù)期一樣,很多文章我都忘記自己曾經(jīng)寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉(zhuǎn)發(fā)。 今天整理了一下近大半年以來的一些文章,和我的預(yù)期一樣,很多文章我都忘記自己曾經(jīng)寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉(zhuǎn)發(fā)。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
閱讀 2737·2021-10-09 09:44
閱讀 3550·2019-08-30 15:54
閱讀 2160·2019-08-30 14:16
閱讀 2790·2019-08-30 13:09
閱讀 826·2019-08-30 13:08
閱讀 1280·2019-08-29 16:29
閱讀 1662·2019-08-26 13:57
閱讀 1925·2019-08-26 13:53