==既比較地址又比較值,.equals()只比較值
java中一共分為8種基本數據類型:byte、short、int、long、float、double、char、boolean
java為每種基本類型都提供了對應的封裝類型,分別為:Byte、Short、Integer、Long、Float、Double、Character、Boolean。引用類型是一種對象類型,它的值是指向內存空間的引用,就是地址。
整型byte、short、int、long的默認值都為0,浮點型float、double的默認值為0.0,boolean默認值為false,char默認值為空。對應的包裝類型默認值都為null。
hashcode不等,equals一定不等,則無需比較equals,提升效率。hashcod相等,equals可能相等。
對象的初始化過程
Person p = new Person("zhangsan",20);
1、因為new用到了Person.class。所以會先找到Person.class文件並加載到內存中。
2、執行該類中的static代碼塊(靜態代碼塊),如果有的話,給Person.class類進行初始化
3、在堆內存中開辟空間,分配內存地址
4、在堆內存中建立對象的特有屬性,並進行默認初始化
5、對屬性進行顯示初始化
6、對對象進行構造代碼塊初始化
7、對對象進行對應的構造函數初始化
8、將內存地址付給棧內存中的p變量
- Thread.sleep(long millis),一定是當前線程調用此方法,當前線程進入阻塞,但不釋放對象鎖,millis后線程自動蘇醒進入可運行狀態。作用:給其它線程執行機會的最佳方式。
- Thread.yield(),一定是當前線程調用此方法,當前線程放棄獲取的cpu時間片,由運行狀態變會可運行狀態,讓OS再次選擇線程。作用:讓相同優先級的線程輪流執行,但並不保證一定會輪流執行。實際中無法保證yield()達到讓步目的,因為讓步的線程還有可能被線程調度程序再次選中。Thread.yield()不會導致阻塞。
- t.join()/t.join(long millis),當前線程里調用其它線程1的join方法,當前線程阻塞,但不釋放對象鎖,直到線程1執行完畢或者millis時間到,當前線程進入可運行狀態。
- obj.wait(),當前線程調用對象的wait()方法,當前線程釋放對象鎖,進入等待隊列。依靠notify()/notifyAll()喚醒或者wait(long timeout)timeout時間到自動喚醒。
- obj.notify()喚醒在此對象監視器上等待的單個線程,選擇是任意性的。notifyAll()喚醒在此對象監視器上等待的所有線程。
常見的5種線程池分別是:
1、FixedThreadPool,它的核心線程數和最大線程數是一樣的,可以把它看成是固定線程數的線程池;
2、CachedThreadPool,可以把它叫做可緩存線程池,它的特點是線程數可以持續增加(理論最大可達Integer.MAX_VALUE=2^31-1);
3、ScheduledThreadPool,它支持定時或周期性的執行任務,有3個方法可以靈活的執行頻率配置參數;
4、SingleThreadExecutor,它會使用唯一的線程去執行任務,適用於所有任務都需要按照被提交的順序依次執行的場景;
5、SingleThreadScheduledExecutor,它和SingleThreadExecutor有些類似,它的核心線程數是1,但是最大線程數是Integer.MAX_VALUE。
ThreadPoolExecutor:
- corePoolSize: 線程池核心線程個數
- workQueue: 用於保存等待執行任務的阻塞隊列
- maximunPoolSize: 線程池最大線程數量
- ThreadFactory: 創建線程的工廠
- RejectedExecutionHandler: 隊列滿,並且線程達到最大線程數量的時候,對新任務的處理策略
- keeyAliveTime: 空閑線程存活時間
- TimeUnit: 存活時間單位
拒絕策略: - AbortPolicy(被拒絕了拋出異常)
- CallerRunsPolicy(使用調用者所在線程執行,就是哪里來的回哪里去)
- DiscardOldestPolicy(嘗試去競爭第一個,失敗了也不拋異常)
- DiscardPolicy(默默丟棄、不拋異常)

volatile是輕量級同步機制。在訪問volatile變量時不會執行加鎖操作,因此也就不會使執行線程阻塞,是一種比synchronized關鍵字更輕量級的同步機制。
保證內存可見性,禁止指令重排(執行順序)
synchronized和ReentrantLock等獨占鎖就是悲觀鎖
樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號機制和CAS算法實現。
synchronized和volatile的完美配合,便實現了線程安全的雙檢鎖單例模式。
為了能讓后繼節點獲取到其前驅節點,同步隊列便設置為雙向鏈表,而等待隊列沒有這樣的需求,就為單鏈表。
Java引用:強 軟 弱 虛
強:只要引用存在,垃圾回收器永遠不會回收
軟:非必須引用,內存溢出之前進行回收
弱引用 是在第二次垃圾回收時回收,短時間內通過弱引用取對應的數據,可以取到,當執行過第二次垃圾回收時,將返回null。
虛引用 是每次垃圾回收的時候都會被回收,通過虛引用的get方法永遠獲取到的數據為null,因此也被成為幽靈引用
泛型:
最后看一下什么是PECS(Producer Extends Consumer Super)原則,已經很好理解了。
Producer Extends 生產者使用Extends來確定上界,往里面放東西來生產
Consumer Super 消費者使用Super來確定下界,往外取東西來消費
1、頻繁往外讀取內容的,適合用上界Extends,即extends 可用於的返回類型限定,不能用於參數類型限定。
2、經常往里插入的,適合用下界Super,super 可用於參數類型限定,不能用於返回類型限定。
3、帶有 super 超類型限定的通配符可以向泛型對象用寫入,帶有 extends 子類型限定的通配符可以向泛型對象讀取;以泛型變量為參數(void set(T t))和以泛型變量(T get())為返回
如果是繼承基類而來的泛型,就用 getGenericSuperclass() , 轉型為 ParameterizedType 來獲得實際類型
如果是實現接口而來的泛型,就用 getGenericInterfaces() , 針對其中的元素轉型為 ParameterizedType 來獲得實際類型
我們所說的 Java 泛型在字節碼中會被擦除,並不總是擦除為 Object 類型,而是擦除到上限類型
能否獲得想要的類型可以在 IDE 中,或用 javap -v <your_class> 來查看泛型簽名來找到線索
類加載:
類加載有三種方式:
1、命令行啟動應用時候由JVM初始化加載
2、通過Class.forName()方法動態加載
3、通過ClassLoader.loadClass()方法動態加載
forName和loaderClass區別
-
Class.forName()得到的class是已經初始化完成的。
-
Classloader.loaderClass得到的class是還沒有鏈接(驗證,准備,解析三個過程被稱為鏈接)的。
三種類加載器,引導(啟動)類加載器,擴展類加載器,系統類加載器(ClassLoader.getSystemClassLoader)

雙親委派模式的好處就是Java類隨着它的類加載器一起具備一種帶有優先級的層次關系,通過這種層級關系可以避免類的重復加載。安全,Java核心API中定義類型不會被隨意替換。
-系統類防止內存中出現多份同樣的字節碼
-保證Java程序安全穩定運行
打破了雙親委派:
對於自己加載不了的類怎么辦,直接用線程上下只要繼承ClassLoader來重寫findClass。如果想打破雙親委派,也要重寫loadClass方法了,做到不委派

堆(GC區),方法區 線程共享
虛擬機,本地方法,程序計算器 線程私有
永久代 jdk1.8 后 元空間:
1、字符串存在永久代中,容易出現性能問題和內存溢出。
2、類及方法的信息等比較難確定其大小,因此對於永久代的大小指定比較困難,太小容易出現永久代溢出,太大則容易導致老年代溢出。
3、永久代會為 GC 帶來不必要的復雜度,並且回收效率偏低。
4、Oracle 可能會將HotSpot 與 JRockit 合二為一。
類加載的過程包括了加載、驗證、准備、解析、初始化五個階段。
GC:
標記:
Java1.2之前主要通過引用計數器來標記是否需要垃圾回收,而1.2之后都使用根搜索算法來收集垃圾
1.引用計數器算法 對象相互引用時候無效
2.根搜索算法(GC ROOT)
回收:
標記-清除算法:
就是當程序運行期間,若可以使用的內存被耗盡的時候,GC線程就會被觸發並將程序暫停,隨后將依舊存活的對象標記一遍,最終再將堆中所有沒被標記的對象全部清除掉,接下來便讓程序恢復運行
效率低
復制算法(新生態GC):
將原有的內存空間分為兩塊,每次只使用其中一塊,在垃圾回收時,將正在使用的內存中的存活對象復制到未使用的內存塊中,之后,清除正在使用的內存塊中的所有對象,交換兩個內存的角色,完成垃圾回收。
空間的浪費
標記-整理算法(老年態GC):
標記-整理/壓縮算法適合用於存活對象較多的場合,如老年代。它在標記-清除算法的基礎上做了一些優化。和標記-清除算法一樣,標記-壓縮算法也首先需要從根節點開始,對所有可達對象做一次標記;但之后,它並不簡單的清理未標記的對象,而是將所有的存活對象壓縮到內存的一端;之后,清理邊界外所有的空間。
從效率上來說,標記/整理算法要低於復制算法。
(1)效率:復制算法>標記/整理算法>標記/清除算法(此處的效率只是簡單的對比時間復雜度,實際情況不一定如此)。
(2)內存整齊度:復制算法=標記/整理算法>標記/清除算法。
(3)內存利用率:標記/整理算法=標記/清除算法>復制算法。
CMS是基於“標記-清除”算法實現的,整個過程分為4個步驟:
1、初始標記(CMS initial mark)。stop the world
2、並發標記(CMS concurrent mark)。
3、重新標記(CMS remark)。stop the world
4、並發清除(CMS concurrent sweep)。

StackOverflowError代表的是,當棧深度超過虛擬機分配給線程的棧大小時就會出現此error。跟jvm的-Xss相關。
棧是運行時的單位,而堆是存儲的單位
棧解決程序的運行問題,即程序如何執行,或者說如何處理數據;堆解決的是數據存儲的問題,即數據怎么放、放在哪兒。
棧內存溢出包括StackOverflowError和OutOfMemoryError。StackOverflowError:線程請求的棧深度大於虛擬機所允許的深度。OutOfMemoryError:如果虛擬機棧可以動態擴展,而擴展時無法申請到足夠的內存;堆內存溢出是OutOfMemoryError。如果堆中沒有內存完成實例分配,並且堆也無法再擴展時,拋出OutOfMemoryError異常。
方法遞歸調用產生StackOverflowError
FTP默認的數據端口號是20,21,22,23。 HTTP默認的端口號是25,80,1024,80。 HTTP服務器,默認的端口號為80/tcp
事務的四大特性分別是:原子性、一致性、隔離性、持久性
(1) git branch 上的修改可以保留,例如在某個branch上commit一個新的節點。checkout到其它branch后commit的節點不會丟。
(2) git tag上的修改 ,checkout到其它branch或者tag后,修改丟失。