程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 阿裡JAVA開發面試常問問題總結4

阿裡JAVA開發面試常問問題總結4

編輯:JAVA綜合教程

阿裡JAVA開發面試常問問題總結4


java的三大特性

封裝、繼承、多態

抽象類和接口的區別

Java抽象類:
使用關鍵字abstract修飾的類叫做抽象類。
用abstract來修飾的方法叫做抽象方法。
特點:
1含有抽象方法的類必須被聲明為抽象類(不管是否還包含其他一般方法)(否則編譯通不過);
2抽象類可以沒有抽象方法,可以有普通方法。
3抽象類必須被繼承,抽象方法必須被重寫:
若子類還是一個抽象類,不需要重寫;否則必須要重寫(override)。
抽象類不能被實例化(不能直接構造一個該類的對象);

抽象方法:
在類中沒有方法體(抽象方法只需聲明,而不需實現某些功能);
抽象類中的抽象方法必須被實現;
如果一個子類沒有實現父類中的抽象方法,則子類也變成了一個抽象類;

虛方法:
虛函數的存在是為了多態。
Java中沒有虛函數的概念。它的普通函數就相當於c++的虛函數,動態綁定是java的默認行為。如果java中不希望某個函數具有虛函數特性,可以加上final關鍵字變為非虛函數。

Java接口:
是一系列方法的聲明。
1只有聲明沒有實現;
2在不同的類中有不同的方法實現;

共同點

1、接口和抽象類都不能被實例化,他們都位於繼承樹的頂端,用於被其他類實現和繼承。
2、接口和抽象類都可以包含抽象方法,實現接口或繼承抽象類的普通子類都必須實現這些方法。

不同點

1、接口裡只能包含抽象方法和默認方法,不能為普通方法提供方法實現;抽象類則完全可以包含普通方法。
2、接口裡不能定義靜態方法,抽象類裡可以定義靜態方法。
3、接口裡只能定義靜態常量,不能定義普通成員變量;抽象類裡則既可以定義普通成員變量,也可以定義靜態常量。
4、接口裡不包含構造器,抽象類裡可以包含構造器,抽象類裡的構造器並不是用於創建對象,而是讓其子類調用這些構造器來完成屬於抽象類的初始化操作。
5、接口裡不能包含初始化塊,但抽象類則完全可以包含初始化塊。
6、一個類最多只能有一個直接父類,包括抽象類;但一個類可以直接實現多個接口,通過實現多個接口可以彌補Java單繼承的不足。

棧內存和堆內存,引用和值傳遞

棧內存、堆內存

在函數中定義的一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配。當在一段代碼塊中定義一個變量時,java就在棧中為這個變量分配內存空間,當超過變量的作用域後,java會自動釋放掉為該變量分配的內存空間,該內存空間可以立刻被另作他用。
堆內存用於存放由new創建的對象和數組。在堆中分配的內存,由java虛擬機自動垃圾回收器來管理。在數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能再被使用,但是仍然占著內存,在隨後的一個不確定的時間被垃圾回收器釋放掉。這個也是java比較占內存的主要原因。

引用、值傳遞

值傳遞:方法調用時,實際參數把它的值傳遞給對應的形式參數,方法執行中形式參數值的改變不影響實際參數的值。

引用傳遞:也稱為傳地址。方法調用時,實際參數的引用(地址,而不是參數的值)被傳遞給方法中相對應的形式參數,在方法執行中,對形式參數的操作實際上就是對實際參數的操作,方法執行中形式參數值的改變將會影響實際參數的值。

單例模式及好處

構造函數私有化,用一個靜態方法來獲取對象實例。

特點:
1)單例類只能有一個實例。
2)單例類必須自己創建自己的唯一實例。
3)單例類必須給所有其他對象提供這一實例。
主要優點:
1)提供了對唯一實例的受控訪問。
2)由於在系統內存中只存在一個對象,因此可以節約系統資源,對於一些需要頻繁創建和銷毀的對象單例模式無疑可以提高系統的性能。
3)允許可變數目的實例。

主要缺點:
1)由於單利模式中沒有抽象層,因此單例類的擴展有很大的困難。
2)單例類的職責過重,在一定程度上違背了“單一職責原則”。
3)濫用單例將帶來一些負面問題,如為了節省資源將數據庫連接池對象設計為的單例類,可能會導致共享連接池對象的程序過多而出現連接池溢出;如果實例化的對象長時間不被利用,系統會認為是垃圾而被回收,這將導致對象狀態的丟失。

重載和重寫

重載:Overloading
(1) Java的方法重載,就是在類中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義。調用方法時通過傳遞給它們的不同參數個數和參數類型來決定具體使用哪個方法, 這就是多態性。
(2) 重載的時候,方法名要一樣,但是參數類型和個數不一樣,返回值類型可以相同也可以不相同。無法以返回類型作為重載函數的區分標准。

重寫:Overriding
注意:當要重寫父類方法時,要使用@Override標簽提醒編譯器檢查代碼是否是重寫,而不是重載了原來的方法。
(1) 父類與子類之間的多態性,對父類的函數進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類並不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要采用方法的重寫。方法重寫又稱方法覆蓋。
(2)若子類中的方法與父類中的某一方法具有相同的方法名、返回類型和參數表,則新方法將覆蓋原有的方法。如需父類中原有的方法,可使用super關鍵字,該關鍵字引用了當前類的父類。
(3)子類函數的訪問修飾權限不能少於父類的。

子類、父類間的轉換和構造順序

子類、父類間的轉換:
子類能夠自動轉換成父類類型。
當創建子類對象的時候:
①先調用了子類的構造函數
②調用了父類的構造函數
③執行了父類的構造函數
④執行了子類的構造函數

Final、finally、finalize

final 用於聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等

Synchronized和volatile的區別

volatile只作用於在多個線程之間能夠被共享的變量。如果一個字段被聲明成volatile,java線程內存模型確保所有線程看到這個變量的值是一致的。Volatile變量修飾符如果使用恰當的話,它比synchronized的使用和執行成本會更低,因為它不會引起線程上下文的切換和調度。
synchronized獲得並釋放監視器——如果兩個線程使用了同一個對象鎖,監視器能強制保證代碼塊同時只被一個線程所執行——這是眾所周知的事實。但是,synchronized也同步內存:事實上,synchronized在“ 主”內存區域同步整個線程的內存。
因此volatile只是在線程內存和“主”內存間同步某個變量的值,而synchronized通過鎖定和解鎖某個監視器同步所有變量的值。顯然synchronized要比volatile消耗更多資源。

1)volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取,沒有互斥鎖;synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
2)volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
3)volatile只是在線程內存和“主”內存間同步某個變量的值,而synchronized通過鎖定和解鎖某個監視器同步所有變量的值;顯然synchronized要比volatile消耗更多資源。
4)volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
5)volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化 。

集合

Collection:代表一組對象,每一個對象都是它的子元素。
Set:不包含重復元素的Collection。
List:有順序的Collection,並且可以包含重復元素。
Map:可以把鍵(key)映射到值(value)的對象,鍵不能重復。

集合類沒有實現Cloneable和Serializable接口的原因

Collection接口指定一組對象,對象即為它的元素。如何維護這些元素由Collection的具體實現決定。例如,一些如List的Collection實現允許重復的元素,而其它的如Set就不允許。很多Collection實現有一個公有的clone方法。然而,把它放到集合的所有實現中也是沒有意義的。這是因為Collection是一個抽象表現。重要的是實現。
當與具體實現打交道的時候,克隆或序列化的語義和含義才發揮作用。所以,具體實現應該決定如何對它進行克隆或序列化,或它是否可以被克隆或序列化。
在所有的實現中授權克隆和序列化,最終導致更少的靈活性和更多的限制。特定的實現應該決定它是否可以被克隆和序列化。

hashCode()和equals()方法的重要性體現在什麼地方?

HashMap使用Key對象的hashCode()和equals()方法去決定key-value對的索引。當我們試著從HashMap中獲取值的時候,這些方法也會被用到。如果這些方法沒有被正確地實現,在這種情況下,兩個不同Key也許會產生相同的hashCode()和equals()輸出,HashMap將會認為它們是相同的,然後覆蓋它們,而非把它們存儲到不同的地方。同樣的,所有不允許存儲重復數據的集合類都使用hashCode()和equals()去查找重復,所以正確實現它們非常重要。
equals()和hashCode()的實現應該遵循以下規則:
(1)如果o1.equals(o2),那麼o1.hashCode() == o2.hashCode()總是為true的。
(2)如果o1.hashCode() == o2.hashCode(),並不意味著o1.equals(o2)會為true。
Java中的HashMap使用hashCode()和equals()方法來確定鍵值對的索引,當根據鍵獲取值的時候也會用到這兩個方法。如果沒有正確的實現這兩個方法,兩個不同的鍵可能會有相同的hash值,因此,可能會被集合認為是相等的。而且,這兩個方法也用來發現重復元素。所以這兩個方法的實現對HashMap的精確性和正確性是至關重要的。

HashMap和HashTabel的區別

HashMap和Hashtable都實現了Map接口,因此很多特性非常相似。但是,他們有以下不同點:
1)HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null。
2)Hashtable是同步的,而HashMap不是。因此,HashMap更適合於單線程環境,而Hashtable適合於多線程環境。
3)HashMap提供了可供應用迭代的鍵的集合,因此,HashMap是快速失敗的。另一方面,Hashtable提供了對鍵的列舉(Enumeration)。
一般認為Hashtable是一個遺留的類。

Comparable和Comparator接口

Comparable和Comparator都是用來實現集合中的排序的,只是Comparable是在集合內部定義的方法實現的排序,Comparator是在集合外部實現的排序,所以,如想實現排序,就需要在集合外定義Comparator接口的方法compare()或在集合內實現Comparable接口的方法compareTo()。
comparable是支持自比較,而後者是支持外部比較;
Comparable是一個對象本身就已經支持自比較所需要實現的接口(如String、Integer自己就可以完成比較大小操作)
而Comparator是一個專用的比較器,當這個對象不支持自比較或者自比較函數不能滿足你的要求時,你可以寫一個比較器來完成兩個對象之間大小的比較。
也就是說當你需要對一個自定義的類的一個數組或者集合進行比較的時候可以實現Comparable接口,當你需要對一個已有的類的數組或者集合進行比較的時候就一定要實現Comparator接口。另外,這兩個接口是支持泛型的,所以我們應該在實現接口的同時定義比較類型。

Java中HashMap的工作原理是?

Java中的HashMap是以鍵值對(key-value)的形式存儲元素的。HashMap需要一個hash函數,它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當調用put()方法的時候,HashMap會計算key的hash值,然後把鍵值對存儲在集合中合適的索引上。如果key已經存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。
1)HashMap有一個叫做Entry的內部類,它用來存儲key-value對。
2)上面的Entry對象是存儲在一個叫做table的Entry數組中。
3)table的索引在邏輯上叫做“桶”(bucket),它存儲了鏈表的第一個元素。
4)key的hashcode()方法用來找到Entry對象所在的桶。
5)如果兩個key有相同的hash值,他們會被放在table數組的同一個桶裡面。
6)key的equals()方法用來確保key的唯一性。
7)value對象的equals()和hashcode()方法根本一點用也沒有。
重點內容
Put:根據key的hashcode()方法計算出來的hash值來決定key在Entry數組的索引。
Get:通過hashcode找到數組中的某一個元素Entry

Hashcode的實現

hashCode 的常規協定是:
在 Java 應用程序執行期間,在同一對象上多次調用 hashCode 方法時,必須一致地返回相同的整數,前提是對象上 equals 比較中所用的信息沒有被修改。從某一應用程序的一次執行到同一應用程序的另一次執行,該整數無需保持一致。
如果根據 equals(Object) 方法,兩個對象是相等的,那麼在兩個對象中的每個對象上調用 hashCode 方法都必須生成相同的整數結果。
當equals方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定聲明相等對象必須具有相等的哈希碼。

String、StringBffer、StringBuilder的區別

1)可變與不可變
String類中使用字符數組保存字符串,如下就是,因為有“final”修飾符,所以可以知道string對象是不可變的。
    private final char value[];
StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,如下就是,可知這兩種對象都是可變的。
    char[] value;
2)是否多線程安全
String中的對象是不可變的,也就可以理解為常量,顯然線程安全。
AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
  StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的

HashMap、HashSet、HashTable的區別

HashSet和HashMap的區別
1)HashSet是set的一個實現類,hashMap是Map的一個實現類,同時hashMap是hashTable的替代品.
2)HashSet以對象作為元素,而HashMap以(key-value)的一組對象作為元素,且HashSet拒絕接受重復的對象.HashMap可以看作三個視圖:key的Set,value的Collection,Entry的Set。HashSet其實就是HashMap的一個視圖。

HashSet內部就是使用Hashmap實現的,和Hashmap不同的是它不需要Key和Value兩個值。
往hashset中插入對象其實只不過是內部做了
public boolean add(Object o) {
return map.put(o, PRESENT)==null;
}

hastTable和hashMap的區別:
1)Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現。
2)這個不同即是最重要的一點:Hashtable中的方法是同步的,而HashMap方法(在缺省情況下)是非同步的。即是說,在多線程應用程序中,不用專門的操作就安全地可以使用Hashtable了;而對於HashMap,則需要額外的同步機制。
3)只有HashMap可以讓你將空值作為一個表的條目的key或value。HashMap中只有一條記錄可以是一個空的key,但任意數量的條目可以是空的value。這就是說,如果在表中沒有發現搜索鍵,或者如果發現了搜索鍵,但它是一個空的值,那麼get()將返回null。如果有必要,用containKey()方法來區別這兩種情況。

線程安全的HashMap —— java.util.concurrent.ConcurrentHashMap
ConcurrentHashMap 增加了Segment 層,每個Segment 原理上等同於一個 Hashtable, ConcurrentHashMap 為 Segment 的數組。
向 ConcurrentHashMap 中插入數據或者讀取數據,首先都要講相應的 Key 映射到對應的 Segment,因此不用鎖定整個類, 只要對單個的 Segment 操作進行上鎖操作就可以了。理論上如果有 n 個 Segment,那麼最多可以同時支持 n 個線程的並發訪問,從而大大提高了並發訪問的效率。另外 rehash() 操作也是對單個的 Segment 進行的,所以由 Map 中的數據量增加導致的 rehash 的成本也是比較低的。

ArrayList和LingkedList的區別

1)ArrayList:底層用數組實現的List
特點:查詢效率高,增刪效率低 輕量級 線程不安全
2)LinkedList:底層用雙向循環鏈表 實現的List
特點:查詢效率低,增刪效率高

垃圾回收機制

Java的垃圾回收機制是Java虛擬機提供的能力,用於在空閒時間以不定時的方式動態回收無任何引用的對象占據的內存空間。
需要注意的是:垃圾回收回收的是無任何引用的對象占據的內存空間而不是對象本身。
兩種常用的方法是引用計數和對象引用遍歷。
引用計數:在這種方法中,堆中每個對象(不是引用)都有一個引用計數。當一個對象被創建時,且將該對象分配給一個變量,該變量計數設置為1。當任何其它變量被賦值為這個對象的引用時,計數加1(a = b,則b引用的對象+1),但當一個對象的某個引用超過了生命周期或者被設置為一個新值時,對象的引用計數減1。任何引用計數為0的對象可以被當作垃圾收集。當一個對象被垃圾收集時,它引用的任何對象計數減1。
對象引用遍歷:從一組對象開始,沿著整個對象圖上的每條鏈接,遞歸確定可到達(reachable)的對象。如果某對象不能從這些根對象的一個(至少一個)到達,則將它作為垃圾收集。

序列化和反序列化

序列化是將對象狀態轉換為可保持或傳輸的格式的過程。與序列化相對的是反序列化,它將流轉換為對象。這兩個過程結合起來,可以輕松地存儲和傳輸數據。
序列化的目的  
1、以某種存儲形式使自定義對象持久化;  
2、將對象從一個地方傳遞到另一個地方。  
3、使程序更具維護性
當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個對象轉換為字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復為對象。
把對象轉換為字節序列的過程稱為對象的序列化。
把字節序列恢復為對象的過程稱為對象的反序列化。
說的再直接點,序列化的目的就是為了跨進程傳遞格式化數據

Java的靈活性體現在什麼機制上?

反射機制

Sleep和wait的區別

1、sleep()方法,是屬於Thread類中的。而wait()方法,則是屬於Object類中的。
2、在調用sleep()方法的過程中,線程不會釋放對象鎖。而當調用wait()方法的時候,線程會放棄對象鎖。
sleep()方法導致了程序暫停執行指定的時間,讓出cpu給其他線程,但是他的監控狀態依然保持著,當指定的時間到了又會自動恢復運行狀態。而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池准備。

IO和NIO

1、IO是面向流的,NIO是面向緩沖區的。
Java IO面向流意味著每次從流中讀一個或多個字節,直至讀取所有字節,它們沒有被緩存在任何地方。此外,它不能前後移動流中的數據。如果需要前後移動從流中讀取的數據,需要先將它緩存到一個緩沖區。 Java NIO的緩沖導向方法略有不同。數據讀取到一個它稍後處理的緩沖區,需要時可在緩沖區中前後移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區中包含所有您需要處理的數據。而且,需確保當更多的數據讀入緩沖區時,不要覆蓋緩沖區裡尚未處理的數據。
2、Java IO的各種流是阻塞的,Java NIO的非阻塞模式。
Java IO的各種流是阻塞的。這意味著,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。 Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什麼都不會獲取。而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閒時間用於在其它通道上執行IO操作,所以一個單獨的線程現在可以管理多個輸入和輸出通道(channel)。
3、Java NIO的選擇器允許一個單獨的線程來監視多個輸入通道,你可以注冊多個通道使用一個選擇器,然後使用一個單獨的線程來“選擇”通道:這些通道裡已經有可以處理的輸入,或者選擇已准備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。而Java IO無選擇器。

Scoket

對於一個功能齊全的Socket,都要包含以下基本結構,其工作過程包含以下四個基本的步驟:
  (1) 創建Socket;
  (2) 打開連接到Socket的輸入/出流;
  (3) 按照一定的協議對Socket進行讀/寫操作;
  (4) 關閉Socket.
 

深克隆、淺克隆

淺復制僅僅復制所考慮的對象,而不復制它所引用的對象。
深復制把要復制的對象所引用的對象都復制了一遍。

在java中只有單繼承,如果要讓一個類賦予新的特性,通常是使用接口來實現。
在c++中支持多繼承,允許一個子類同時具有多個父類的接口和功能。

UDP和TCP

UDP和TCP都屬於傳輸層協議。
TCP協議:面向連接的、可靠的、基於字節流
UDP協議:無連接、不可靠、基於報文
1、TCP協議中包含了專門的傳遞保證機制,當數據接收方收到發送方傳來的信息時,會自動向發送方發出確認消息;發送方只有在接收到該確認消息之後才繼續傳送其它信息,否則將一直等待直到收到確認信息為止。
與TCP不同,UDP協議並不提供數據傳送的保證機制。如果在從發送方到接收方的傳遞過程中出現數據報的丟失,協議本身並不能做出任何檢測或提示。因此,通常人們把UDP協議稱為不可靠的傳輸協議。
2、相對於TCP協議,UDP協議的另外一個不同之處在於如何接收突發性的多個數據報。不同於TCP,UDP並不能確保數據的發送和接收順序。

紅黑樹

是一種自平衡二叉查找樹,紅黑樹是一種很有意思的平衡檢索樹;每次插入的時候都要進行計算,保證二叉樹的平衡;如果有2的N次方數據量級,查詢的時候只需要查詢N次即可。
我們對任何有效的紅黑樹加以如下增補要求:
1.節點是紅色或黑色。
2.根是黑色。
3.所有葉子(外部節點)都是黑色。
4.每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
5.從每個葉子到根的所有路徑都包含相同數目的黑色節點。
這些約束強制了紅黑樹的關鍵屬性: 從根到葉子的最長的可能路徑不多於最短的可能路徑的兩倍長。結果是這個樹大致上是平衡的。

反射

反射機制指的是程序在運行時能夠獲取自身的信息。
用反射機制實現對數據庫數據的增、查例子 。
基本原理:保存數據時,把需要保存的對象的屬性值全部取出來再拼湊sql語句;查詢時,將查詢到的數據全部包裝成一個java對象。
1)數據庫的每一個表對應一個pojo類,表中的每一個字段對應pojo類的中的一個屬性。 並且pojo類的名字和表的名字相同,屬性名和字段名相同,大小寫沒有關系,因為數據庫一般不區分大小寫
2)為pojo類中的每一個屬性添加標准的set和get方法。

三次握手和四次揮手

三次握手:首先Client端發送連接請求報文,Server段接受連接後回復ACK報文,並為這次連接分配資源。Client端接收到ACK報文後也向Server段發送ACK報文,並分配資源,這樣TCP連接就建立了。

四次握手:
由於TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數據流動,一個TCP連接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
(1) TCP客戶端發送一個FIN,用來關閉客戶到服務器的數據傳送。
(2) 服務器收到這個FIN,它發回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將占用一個序號。
(3) 服務器關閉客戶端的連接,發送一個FIN給客戶端。
(4) 客戶端發回ACK報文確認,並將確認序號設置為收到序號加1。

Equals()和== 

  1、java中equals和==的區別 值類型是存儲在內存中的堆棧(簡稱棧),而引用類型的變量在棧中僅僅是存儲引用類型變量的地址,而其本身則存儲在堆中。
  2、==操作比較的是兩個變量的值是否相等,對於引用型變量表示的是兩個變量在堆中存儲的地址是否相同,即棧中的內容是否相同。
  3、equals操作表示的兩個變量是否是對同一個對象的引用,即堆中的內容是否相同。
  4、==比較的是2個對象的地址,而equals比較的是2個對象的內容,顯然,當equals為true時,==不一定為true。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved