JAVA基礎(chǔ)

equals和==有什么區(qū)別

"=="是是不是指向同一個內(nèi)存空間。
"equals"是判斷所指向的內(nèi)存空間的值是不是相同。
"equals"是方法。
"=="是運算符合。
"=="比"equals"運行速度快,因為"=="只是比較引用。

權(quán)限修飾符

抽象類和接口區(qū)別

  • 定義和實現(xiàn)功能的限制不同。在接口中只允許定義,不允許對方法進行實現(xiàn),并且接口中定義的屬性不可改變;在抽象類中可以有一般方法的實現(xiàn),也可以有抽象方法,可以定義變量。
  • 一個類只能繼承一個父類,但是一個類可以實現(xiàn)多個接口
    修飾的關(guān)鍵字有區(qū)別。在接口中,所有方法都只能用public,abstract這兩個關(guān)鍵字來修飾,所有定義的成員變量為public,static,final。而在抽象類中,可以有自己的成員變量和方法,也可以有非抽象的成員方法;而且,在抽象類中,抽象類的成員變量默認為default,當(dāng)然也可以自行定義為public,protected,private,這些成員變量在子類中可以重新被定義也可以重新被賦值;但是抽象類中的抽象方法(方法前有abstract修飾)不能用private,static,synchronized和native等訪問修飾符來修飾。
  • 應(yīng)用的功能場景不同。接口被用于實現(xiàn)比較常用的功能,便于日后維護或者添加刪除方法,而抽象類更傾向于公共類的角色,不適用于日后重對里面的代碼進行修改。

深拷貝和淺拷貝

淺拷貝只復(fù)制指向某個對象的指針,而不復(fù)制對象本身,新舊對象還是共享同一塊內(nèi)存。但深拷貝會另外創(chuàng)造一個一模一樣的對象,新對象跟原對象不共享內(nèi)存,修改新對象不會改到原對象。

&和&& (|和||同理)

1.運算符性質(zhì)不同。

&是一個位運算符。

&&是一個邏輯運算符。

2.作用不同。

&是將兩個二進制的數(shù)逐位相與,結(jié)果是相遇之后的結(jié)果。

&&就是判斷兩個表達式的真假性,只有兩個表達式同時為真才為真,有一個為假則為假,具有短路性質(zhì)。

https://blog.csdn.net/lonelyroamer/article/details/7949969

線程產(chǎn)生死鎖的四個必備條件及解決方法

產(chǎn)生死鎖的四個必要條件
(1) 互斥條件:該資源任意一個時刻只由一個線程占用。
(2)請求與保持條件:一個進程因請求某資源而堵塞時,對已獲得的資源保持不放。
(3)不剝奪條件:線程已獲得的資源在未使用完之前不能被其他線程強行掠奪,只有自己使用完之后才能釋放資源。
(4)循環(huán)等待條件:**若干進程之間形成的一種頭尾相接的循環(huán)等待資源關(guān)系。

解決方法
(1)破壞請求與保持條件:一次性申請所有需要用到的資源。
(2)破壞不剝奪條件:占用部分資源的線程進一步申請不到其他的資源時,可以主動釋放它占有的資源。
(3)破壞循環(huán)等待條件:按某種序申請資源,釋放資源則反序釋放,破壞循環(huán)等待條件。

強軟弱虛引用

1,強引用
強引用是使用最多的引用,如果一個對象具有強引用,那么在該對象時不會被gc所回收的。

Object object = new Object(); //強引用
當(dāng)內(nèi)存空間不足,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內(nèi)存不足的問題。如果不使用時,要通過如下方式來弱化引用,如下:

object = null //將該對象弱化,這樣一來gc才能夠成功回收該數(shù)據(jù)
在一個方法的內(nèi)部有一個強引用,這個引用保存在棧中,而真正的引用內(nèi)容(Object)保存在堆中。當(dāng)這個方法運行完成后就會退出方法棧,則引用內(nèi)容的引用不存在,這個Object會被回收。
但是如果這個object是全局的變量時,就需要在不用這個對象時賦值為null,因為強引用不會被垃圾回收。

2、軟引用(SoftReference)
如果一個對象只具有軟引用,則內(nèi)存空間足夠,垃圾回收器就不會回收它;如果內(nèi)存空間不足了,就會回收這些對象的內(nèi)存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。

String str=new String(“abc”); // 強引用
SoftReference softRef=new SoftReference(str); // 軟引用
3、弱引用(WeakReference)
弱引用與軟引用的區(qū)別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象,不管當(dāng)前內(nèi)存空間足夠與否,都會回收它的內(nèi)存。不過,由于垃圾回收器是一個優(yōu)先級很低的線程,因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象。

String str=new String(“abc”);
WeakReference abcWeakRef = new WeakReference(str);
str=null
當(dāng)垃圾回收器進行掃描回收時等價于:

str = null;
System.gc();
如果這個對象是偶爾的使用,并且希望在使用時隨時就能獲取到,但又不想影響此對象的垃圾收集,那么你應(yīng)該用 WeakReference 來記住此對象。

下面的代碼會讓str再次變?yōu)橐粋€強引用:

String abc = abcWeakRef.get();
弱引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關(guān)聯(lián)的引用隊列中。

當(dāng)你想引用一個對象,但是這個對象有自己的生命周期,你不想介入這個對象的生命周期,這時候你就是用弱引用。

package reference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.LinkedList;

public class ReferenceTest {
    private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();
    public static void checkQueue() {
        Reference<? extends VeryBig> ref = null;
        while ((ref = rq.poll()) != null) {
            if (ref != null) {
                System.out.println("In queue: "
                        + ((VeryBigWeakReference) (ref)).id);
            }
        }
    }
    public static void main(String args[]) {
        int size = 3;
        LinkedList<WeakReference<VeryBig>> weakList = new LinkedList<WeakReference<VeryBig>>();
        for (int i = 0; i < size; i++) {
            weakList.add(new VeryBigWeakReference(new VeryBig("Weak " + i), rq));
            System.out.println("Just created weak: " + weakList.getLast());
        }
        System.gc();
        try { // 下面休息幾分鐘,讓上面的垃圾回收線程運行完成
            Thread.currentThread().sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        checkQueue();
    }
}

class VeryBig {
    public String id;
    // 占用空間,讓線程進行回收
    byte[] b = new byte[2 * 1024];
    public VeryBig(String id) {
        this.id = id;
    }
    protected void finalize() {
        System.out.println("Finalizing VeryBig " + id);
    }
}

class VeryBigWeakReference extends WeakReference<VeryBig> {
    public String id;
    public VeryBigWeakReference(VeryBig big, ReferenceQueue<VeryBig> rq) {
        super(big, rq);
        this.id = big.id;
    }
    protected void finalize() {
        System.out.println("Finalizing VeryBigWeakReference " + id);
    }
}

結(jié)果為

Just created weak: reference.VeryBigWeakReference@570f80a9
Just created weak: reference.VeryBigWeakReference@3ac803e6
Just created weak: reference.VeryBigWeakReference@21780f30
Finalizing VeryBig Weak 0
Finalizing VeryBig Weak 2
Finalizing VeryBig Weak 1
In queue: Weak 0
In queue: Weak 1
In queue: Weak 2

4、虛引用(PhantomReference)
“虛引用”顧名思義,就是形同虛設(shè),與其他幾種引用都不同,虛引用并不會決定對象的生命周期。如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。

虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區(qū)別在于:虛引用必須和引用隊列(ReferenceQueue)聯(lián)合使用。當(dāng)垃圾回收器準備回收一個對象時,如果發(fā)現(xiàn)它還有虛引用,就會在回收對象的內(nèi)存之前,把這個虛引用加入到與之關(guān)聯(lián)的引用隊列中。

Java4種引用的級別由高到低依次為:

強引用 > 軟引用 > 弱引用 > 虛引用

https://blog.csdn.net/WJHelloWorld/article/details/78460831

TCP 和 UDP

1、TCP 面向連接(如打電話要先撥號建立連接); UDP 是無連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接。

2、TCP 提供可靠的服務(wù)。也就是說,通過 TCP 連接傳送的數(shù)據(jù),無差錯,不丟失,不重復(fù),且按序到達;UDP 盡最大努力交付,即不保證可靠交付。

3、TCP 面向字節(jié)流,實際上是 TCP 把數(shù)據(jù)看成一連串無結(jié)構(gòu)的字節(jié)流;UDP 是面向報文的。UDP 沒有擁塞控制,因此網(wǎng)絡(luò)出現(xiàn)擁塞不會使源主機的發(fā)送速率降低(對實時應(yīng)用很有用,如IP電話,實時視頻會議等)

4、每一條 TCP 連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信。

5、TCP 首部開銷 20 字節(jié);UDP 的首部開銷小,只有 8 個字節(jié)。

6、TCP 的邏輯通信信道是全雙工的可靠信道,UDP 則是不可靠信道。

單例模式的實現(xiàn)有多種方式,如下所示:

1、懶漢式,線程不安全
是否 Lazy 初始化:是
是否多線程安全:否
實現(xiàn)難度:易
描述:這種方式是最基本的實現(xiàn)方式,這種實現(xiàn)最大的問題就是不支持多線程。因為沒有加鎖 synchronized,所以嚴格意義上它并不算單例模式。
這種方式 lazy loading 很明顯,不要求線程安全,在多線程不能正常工作。
實例
public class Singleton {
private static Singleton instance;
private Singleton (){}

public static Singleton getInstance() {  
if (instance == null) {  
    instance = new Singleton();  
}  
return instance;  
}  

}
接下來介紹的幾種實現(xiàn)方式都支持多線程,但是在性能上有所差異。
2、懶漢式,線程安全
是否 Lazy 初始化:是
是否多線程安全:是
實現(xiàn)難度:易
描述:這種方式具備很好的 lazy loading,能夠在多線程中很好的工作,但是,效率很低,99% 情況下不需要同步。
優(yōu)點:第一次調(diào)用才初始化,避免內(nèi)存浪費。
缺點:必須加鎖 synchronized 才能保證單例,但加鎖會影響效率。
getInstance() 的性能對應(yīng)用程序不是很關(guān)鍵(該方法使用不太頻繁)。
實例
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3、餓漢式
是否 Lazy 初始化:否
是否多線程安全:是
實現(xiàn)難度:易
描述:這種方式比較常用,但容易產(chǎn)生垃圾對象。
優(yōu)點:沒有加鎖,執(zhí)行效率會提高。
缺點:類加載時就初始化,浪費內(nèi)存。
它基于 classloader 機制避免了多線程的同步問題,不過,instance 在類裝載時就實例化,雖然導(dǎo)致類裝載的原因有很多種,在單例模式中大多數(shù)都是調(diào)用 getInstance 方法, 但是也不能確定有其他的方式(或者其他的靜態(tài)方法)導(dǎo)致類裝載,這時候初始化 instance 顯然沒有達到 lazy loading 的效果。
實例
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
4、雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)
JDK 版本:JDK1.5 起
是否 Lazy 初始化:是
是否多線程安全:是
實現(xiàn)難度:較復(fù)雜
描述:這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能。
getInstance() 的性能對應(yīng)用程序很關(guān)鍵。
實例
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容