面向?qū)ο缶幊蹋∣OP)
Java是一個支持并發(fā)宽闲、基于類和面向?qū)ο蟮挠嬎銠C編程語言。下面列出了面向?qū)ο筌浖_發(fā)的優(yōu)點:
- 代碼開發(fā)模塊化,更易維護和修改缀程。
- 代碼復(fù)用。
- 增強代碼的可靠性和靈活性市俊。
- 增加代碼的可理解性杨凑。
面向?qū)ο缶幊逃泻芏嘀匾奶匦裕热纾悍庋b摆昧,繼承撩满,多態(tài)和抽象。下面的章節(jié)我們會逐個分析這些特性绅你。
封裝
封裝給對象提供了隱藏內(nèi)部特性和行為的能力鹦牛。對象提供一些能被其他對象訪問的方法來改變它內(nèi)部的數(shù)據(jù)。在Java當中勇吊,有4種修飾符:public曼追,private、protected和默認汉规。每一種修飾符給其他的位于同一個包或者不同包下面對象賦予了不同的訪問權(quán)限礼殊。
下面列出了使用封裝的一些好處:
- 通過隱藏對象的屬性來保護對象內(nèi)部的狀態(tài)。
- 提高了代碼的可用性和可維護性针史,因為對象的行為可以被單獨的改變或者是擴展晶伦。
- 禁止對象之間的不良交互提高模塊化。
參考這個文檔獲取更多關(guān)于封裝的細節(jié)和示例啄枕。
多態(tài)
多態(tài)是編程語言給不同的底層數(shù)據(jù)類型做相同的接口展示的一種能力婚陪。一個多態(tài)類型上的操作可以應(yīng)用到其他類型的值上面。
繼承
繼承給對象提供了從基類獲取字段和方法的能力频祝。繼承提供了代碼的重用行泌参,也可以在不修改類的情況下給現(xiàn)存的類添加新特性。
抽象
抽象是把想法從具體的實例中分離出來的步驟常空,因此哨免,要根據(jù)他們的功能而不是實現(xiàn)細節(jié)來創(chuàng)建類考杉。Java支持創(chuàng)建只暴漏接口而不包含方法實現(xiàn)的抽象的類。這種抽象技術(shù)的主要目的是把類的行為和實現(xiàn)細節(jié)分離開。
抽象和封裝的不同點
抽象和封裝是互補的概念工扎。一方面,抽象關(guān)注對象的行為。另一方面,封裝關(guān)注對象行為的細節(jié)蝇庭。一般是通過隱藏對象內(nèi)部狀態(tài)信息做到封裝,因此捡硅,封裝可以看成是用來提供抽象的一種策略遗契。
常見的Java問題
- 什么是Java虛擬機?為什么Java被稱作是“平臺無關(guān)的編程語言”病曾?
Java虛擬機是一個可以執(zhí)行Java字節(jié)碼的虛擬機進程牍蜂。Java源文件被編譯成能被Java虛擬機執(zhí)行的字節(jié)碼文件。
Java被設(shè)計成允許應(yīng)用程序可以運行在任意的平臺泰涂,而不需要程序員為每一個平臺單獨重寫或者是重新編譯鲫竞。Java虛擬機讓這個變?yōu)榭赡埽驗樗赖讓佑布脚_的指令長度和其他特性逼蒙。
- JDK和JRE的區(qū)別是什么从绘?
Java運行時環(huán)境(JRE)是將要執(zhí)行Java程序的Java虛擬機。它同時也包含了執(zhí)行applet需要的瀏覽器插件是牢。Java開發(fā)工具包(JDK)是完整的Java軟件開發(fā)包僵井,包含了JRE,編譯器和其他的工具(比如:JavaDoc驳棱,Java調(diào)試器)批什,可以讓開發(fā)者開發(fā)、編譯社搅、執(zhí)行Java應(yīng)用程序驻债。
- ”static”關(guān)鍵字是什么意思?Java中是否可以覆蓋(override)一個private或者是static的方法形葬?
“static”關(guān)鍵字表明一個成員變量或者是成員方法可以在沒有所屬的類的實例變量的情況下被訪問合呐。
Java中static方法不能被覆蓋,因為方法覆蓋是基于運行時動態(tài)綁定的笙以,而static方法是編譯時靜態(tài)綁定的淌实。static方法跟類的任何實例都不相關(guān),所以概念上不適用猖腕。
- 是否可以在static環(huán)境中訪問非static變量拆祈?
static變量在Java中是屬于類的,它在所有的實例中的值是一樣的谈息。當類被Java虛擬機載入的時候缘屹,會對static變量進行初始化。如果你的代碼嘗試不用實例來訪問非static的變量侠仇,編譯器會報錯,因為這些變量還沒有被創(chuàng)建出來,還沒有跟任何實例關(guān)聯(lián)上逻炊。
- Java支持的數(shù)據(jù)類型有哪些互亮?什么是自動拆裝箱?
-
Java語言支持的8中基本數(shù)據(jù)類型是:
- byte
- short
- int
- long
- float
- double
- boolean
- char
自動裝箱是Java編譯器在基本數(shù)據(jù)類型和對應(yīng)的對象包裝類型之間做的一個轉(zhuǎn)化余素。比如:把int轉(zhuǎn)化成Integer豹休,double轉(zhuǎn)化成double,等等桨吊。反之就是自動拆箱威根。
- Java中的方法覆蓋(Overriding)和方法重載(Overloading)是什么意思?
Java中的方法重載發(fā)生在同一個類里面兩個或者是多個方法的方法名相同但是參數(shù)不同的情況视乐。與此相對洛搀,方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名佑淀,參數(shù)列表和返回類型留美。覆蓋者可能不會限制它所覆蓋的方法的訪問。
- Java中伸刃,什么是構(gòu)造函數(shù)谎砾?什么是構(gòu)造函數(shù)重載?什么是復(fù)制構(gòu)造函數(shù)捧颅?
當新對象被創(chuàng)建的時候景图,構(gòu)造函數(shù)會被調(diào)用。每一個類都有構(gòu)造函數(shù)碉哑。在程序員沒有給類提供構(gòu)造函數(shù)的情況下症歇,Java編譯器會為這個類創(chuàng)建一個默認的構(gòu)造函數(shù)。
Java中構(gòu)造函數(shù)重載和方法重載很相似谭梗⊥睿可以為一個類創(chuàng)建多個構(gòu)造函數(shù)。每一個構(gòu)造函數(shù)必須有它自己唯一的參數(shù)列表激捏。
Java不支持像C++中那樣的復(fù)制構(gòu)造函數(shù)设塔,這個不同點是因為如果你不自己寫構(gòu)造函數(shù)的情況下,Java不會創(chuàng)建默認的復(fù)制構(gòu)造函數(shù)远舅。
- Java支持多繼承么闰蛔?
不支持,Java不支持多繼承图柏。每個類都只能繼承一個類序六,但是可以實現(xiàn)多個接口。
- 接口和抽象類的區(qū)別是什么蚤吹?
-
Java提供和支持創(chuàng)建抽象類和接口例诀。它們的實現(xiàn)有共同點随抠,不同點在于:
- 接口中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法繁涂。
- 類可以實現(xiàn)很多個接口拱她,但是只能繼承一個抽象類
- 類如果要實現(xiàn)一個接口,它必須要實現(xiàn)接口聲明的所有方法扔罪。但是秉沼,類可以不實現(xiàn)抽象類聲明的所有方法,當然矿酵,在這種情況下唬复,類也必須得聲明成是抽象的。
- 抽象類可以在不提供接口方法實現(xiàn)的情況下實現(xiàn)接口全肮。
- Java接口中聲明的變量默認都是final的敞咧。抽象類可以包含非final的變量。
- Java接口中的成員函數(shù)默認是public的倔矾。抽象類的成員函數(shù)可以是private妄均,protected或者是public。
- 接口是絕對抽象的哪自,不可以被實例化丰包。抽象類也不可以被實例化,但是壤巷,如果它包含main方法的話是可以被調(diào)用的邑彪。
也可以參考JDK8中抽象類和接口的區(qū)別
- 什么是值傳遞和引用傳遞?
對象被值傳遞胧华,意味著傳遞了對象的一個副本寄症。因此,就算是改變了對象副本矩动,也不會影響源對象的值有巧。
對象被引用傳遞,意味著傳遞的并不是實際的對象悲没,而是對象的引用篮迎。因此,外部對引用對象所做的改變會反映到所有的對象上示姿。
Java線程
- 進程和線程的區(qū)別是什么甜橱?
進程是執(zhí)行著的應(yīng)用程序,而線程是進程內(nèi)部的一個執(zhí)行序列栈戳。一個進程可以有多個線程岂傲。線程又叫做輕量級進程。
-
創(chuàng)建線程有幾種不同的方式子檀?你喜歡哪一種镊掖?為什么乃戈?
-
有三種方式可以用來創(chuàng)建線程:
- 繼承Thread類
- 實現(xiàn)Runnable接口
- 應(yīng)用程序可以使用Executor框架來創(chuàng)建線程池
-
實現(xiàn)Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類堰乔。在應(yīng)用設(shè)計中已經(jīng)繼承了別的對象的情況下偏化,這需要多繼承(而Java不支持多繼承)脐恩,只能實現(xiàn)接口镐侯。同時,線程池也是非常高效的驶冒,很容易實現(xiàn)和使用苟翻。
-
概括的解釋下線程的幾種可用狀態(tài)。
-
線程在執(zhí)行過程中骗污,可以處于下面幾種狀態(tài):
- 就緒(Runnable):線程準備運行崇猫,不一定立馬就能開始執(zhí)行。
- 運行中(Running):進程正在執(zhí)行線程的代碼需忿。
- 等待中(Waiting):線程處于阻塞的狀態(tài)诅炉,等待外部的處理結(jié)束。
- 睡眠中(Sleeping):線程被強制睡眠屋厘。
- I/O阻塞(Blocked on I/O):等待I/O操作完成涕烧。
- 同步阻塞(Blocked on Synchronization):等待獲取鎖。
- 死亡(Dead):線程完成了執(zhí)行汗洒。
-
同步方法和同步代碼塊的區(qū)別是什么议纯?
在Java語言中,每一個對象有一把鎖溢谤。線程可以使用synchronized關(guān)鍵字來獲取對象上的鎖瞻凤。synchronized關(guān)鍵字可應(yīng)用在方法級別(粗粒度鎖)或者是代碼塊級別(細粒度鎖)。
- 在監(jiān)視器(Monitor)內(nèi)部世杀,是如何做線程同步的阀参?程序應(yīng)該做哪種級別的同步?
監(jiān)視器和鎖在Java虛擬機中是一塊使用的瞻坝。監(jiān)視器監(jiān)視一塊同步代碼塊蛛壳,確保一次只有一個線程執(zhí)行同步代碼塊。每一個監(jiān)視器都和一個對象引用相關(guān)聯(lián)湿镀。線程在獲取鎖之前不允許執(zhí)行同步代碼炕吸。
- 什么是死鎖(deadlock)?
兩個進程都在等待對方執(zhí)行完畢才能繼續(xù)往下執(zhí)行的時候就發(fā)生了死鎖勉痴。結(jié)果就是兩個進程都陷入了無限的等待中赫模。
- 如何確保N個線程可以訪問N個資源同時又不導(dǎo)致死鎖?
使用多線程的時候蒸矛,一種非常簡單的避免死鎖的方式就是:指定獲取鎖的順序瀑罗,并強制線程按照指定的順序獲取鎖胸嘴。因此,如果所有的線程都是以同樣的順序加鎖和釋放鎖斩祭,就不會出現(xiàn)死鎖了劣像。
Java集合類
-
Java集合類框架的基本接口有哪些?
-
Java集合類提供了一套設(shè)計良好的支持對一組對象進行操作的接口和類摧玫。Java集合類里面最基本的接口有:
- Collection:代表一組對象耳奕,每一個對象都是它的子元素。
- Set:不包含重復(fù)元素的Collection诬像。
- List:有順序的collection屋群,并且可以包含重復(fù)元素。
- Map:可以把鍵(key)映射到值(value)的對象坏挠,鍵不能重復(fù)芍躏。
-
為什么集合類沒有實現(xiàn)Cloneable和Serializable接口?
集合類接口指定了一組叫做元素的對象降狠。集合類接口的每一種具體的實現(xiàn)類都可以選擇以它自己的方式對元素進行保存和排序对竣。有的集合類允許重復(fù)的鍵,有些不允許榜配。
- 什么是迭代器(Iterator)否纬?
Iterator接口提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器實例的
迭代方法芥牌。迭代器可以在迭代的過程中刪除底層集合的元素烦味。
克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實現(xiàn)相關(guān)的。因此壁拉,應(yīng)該由集合類的具體實現(xiàn)來決定如何被克隆或者是序列化谬俄。
-
Iterator和ListIterator的區(qū)別是什么?
-
下面列出了他們的區(qū)別:
- Iterator可用來遍歷Set和List集合弃理,但是ListIterator只能用來遍歷List溃论。
- Iterator對集合只能是前向遍歷,ListIterator既可以前向也可以后向痘昌。
- ListIterator實現(xiàn)了Iterator接口钥勋,并包含其他的功能,比如:增加元素辆苔,替換元素算灸,獲取前一個和后一個元素的索引,等等驻啤。
-
快速失敗(fail-fast)和安全失敗(fail-safe)的區(qū)別是什么菲驴?
Iterator的安全失敗是基于對底層集合做拷貝,因此骑冗,它不受源集合上修改的影響赊瞬。java.util包下面的所有的集合類都是快速失敗的先煎,而java.util.concurrent包下面的所有的類都是安全失敗的∏山В快速失敗的迭代器會拋出ConcurrentModificationException異常薯蝎,而安全失敗的迭代器永遠不會拋出這樣的異常。
- Java中的HashMap的工作原理是什么谤绳?
Java中的HashMap是以鍵值對(key-value)的形式存儲元素的占锯。HashMap需要一個hash函數(shù),它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素闷供。當調(diào)用put()方法的時候烟央,HashMap會計算key的hash值统诺,然后把鍵值對存儲在集合中合適的索引上歪脏。如果key已經(jīng)存在了,value會被更新成新值粮呢。HashMap的一些重要的特性是它的容量(capacity)婿失,負載因子(load factor)和擴容極限(threshold resizing)。
- hashCode()和equals()方法的重要性體現(xiàn)在什么地方啄寡?
Java中的HashMap使用hashCode()和equals()方法來確定鍵值對的索引豪硅,當根據(jù)鍵獲取值的時候也會用到這兩個方法。如果沒有正確的實現(xiàn)這兩個方法挺物,兩個不同的鍵可能會有相同的hash值懒浮,因此,可能會被集合認為是相等的识藤。而且砚著,這兩個方法也用來發(fā)現(xiàn)重復(fù)元素。所以這兩個方法的實現(xiàn)對HashMap的精確性和正確性是至關(guān)重要的痴昧。
-
HashMap和Hashtable有什么區(qū)別稽穆?
- HashMap和Hashtable都實現(xiàn)了Map接口,因此很多特性非常相似赶撰。但是舌镶,他們有以下不同點:
- HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null豪娜。
- Hashtable是同步的餐胀,而HashMap不是。因此瘤载,HashMap更適合于單線程環(huán)境否灾,而Hashtable適合于多線 程環(huán)境。
- HashMap提供了可供應(yīng)用迭代的鍵的集合惕虑,因此坟冲,HashMap是快速失敗的磨镶。另一方面,Hashtable提供了對鍵的列舉(Enumeration)健提。
- 一般認為Hashtable是一個遺留的類琳猫。
-
數(shù)組(Array)和列表(ArrayList)有什么區(qū)別?什么時候應(yīng)該使用Array而不是ArrayList私痹?
-
下面列出了Array和ArrayList的不同點:
- Array可以包含基本類型和對象類型脐嫂,ArrayList只能包含對象類型。
- Array大小是固定的紊遵,ArrayList的大小是動態(tài)變化的账千。
- ArrayList提供了更多的方法和特性,比如:addAll()暗膜,removeAll()匀奏,iterator()等等。
- 對于基本類型數(shù)據(jù)学搜,集合使用自動裝箱來減少編碼工作量娃善。但是,當處理固定大小的基本數(shù)據(jù)類型的時候瑞佩,這種方式相對比較慢聚磺。
-
-
ArrayList和LinkedList有什么區(qū)別?
-
ArrayList和LinkedList都實現(xiàn)了List接口炬丸,他們有以下的不同點:
ArrayList是基于索引的數(shù)據(jù)接口瘫寝,它的底層是數(shù)組。它可以以O(shè)(1)時間復(fù)雜度對元素進行隨機訪問稠炬。與此對應(yīng)焕阿,LinkedList是以元素列表的形式存儲它的數(shù)據(jù),每一個元素都和它的前一個和后一個元素鏈接在一起酸纲,在這種情況下捣鲸,查找某個元素的時間復(fù)雜度是O(n)。
相對于ArrayList闽坡,LinkedList的插入栽惶,添加,刪除操作速度更快疾嗅,因為當元素被添加到集合任意位置的時候外厂,不需要像數(shù)組那樣重新計算大小或者是更新索引。
LinkedList比ArrayList更占內(nèi)存代承,因為LinkedList為每一個節(jié)點存儲了兩個引用汁蝶,一個指向前一個元素,一個指向下一個元素。
-
也可以參考ArrayList vs. LinkedList掖棉。
- Comparable和Comparator接口是干什么的墓律?列出它們的區(qū)別。
Java提供了只包含一個compareTo()方法的Comparable接口幔亥。這個方法可以個給兩個對象排序耻讽。具體來說,它返回負數(shù)帕棉,0针肥,正數(shù)來表明輸入對象小于,等于香伴,大于已經(jīng)存在的對象慰枕。
Java提供了包含compare()和equals()兩個方法的Comparator接口。compare()方法用來給兩個輸入?yún)?shù)排序即纲,返回負數(shù)具帮,0,正數(shù)表明第一個參數(shù)是小于崇裁,等于匕坯,大于第二個參數(shù)。equals()方法需要一個對象作為參數(shù)拔稳,它用來決定輸入?yún)?shù)是否和comparator相等。只有當輸入?yún)?shù)也是一個comparator并且輸入?yún)?shù)和當前comparator的排序結(jié)果是相同的時候锹雏,這個方法才返回true巴比。
- 什么是Java優(yōu)先級隊列(Priority Queue)?
PriorityQueue是一個基于優(yōu)先級堆的無界隊列礁遵,它的元素是按照自然順序(natural order)排序的轻绞。在創(chuàng)建的時候,我們可以給它提供一個負責給元素排序的比較器佣耐。PriorityQueue不允許null值政勃,因為他們沒有自然順序,或者說他們沒有任何的相關(guān)聯(lián)的比較器兼砖。最后奸远,PriorityQueue不是線程安全的,入隊和出隊的時間復(fù)雜度是O(log(n))讽挟。
- 你了解大O符號(big-O notation)么懒叛?你能給出不同數(shù)據(jù)結(jié)構(gòu)的例子么?
大O符號描述了當數(shù)據(jù)結(jié)構(gòu)里面的元素增加的時候耽梅,算法的規(guī)难或者是性能在最壞的場景下有多么好。
大O符號也可用來描述其他的行為眼姐,比如:內(nèi)存消耗诅迷。因為集合類實際上是數(shù)據(jù)結(jié)構(gòu)佩番,我們一般使用大O符號基于時間,內(nèi)存和性能來選擇最好的實現(xiàn)罢杉。大O符號可以對大量數(shù)據(jù)的性能給出一個很好的說明答捕。
- 如何權(quán)衡是使用無序的數(shù)組還是有序的數(shù)組?
有序數(shù)組最大的好處在于查找的時間復(fù)雜度是O(log n)屑那,而無序數(shù)組是O(n)拱镐。有序數(shù)組的缺點是插入操作的時間復(fù)雜度是O(n),因為值大的元素需要往后移動來給新元素騰位置持际。相反沃琅,無序數(shù)組的插入時間復(fù)雜度是常量O(1)。
-
Java集合類框架的最佳實踐有哪些蜘欲?
- 根據(jù)應(yīng)用的需要正確選擇要使用的集合的類型對性能非常重要益眉,比如:假如元素的大小是固定的,而且能事先知道姥份,我們就應(yīng)該用Array而不是ArrayList郭脂。
- 有些集合類允許指定初始容量。因此澈歉,如果我們能估計出存儲的元素的數(shù)目展鸡,我們可以設(shè)置初始容量來避免重新計算hash值或者是擴容。
- 為了類型安全埃难,可讀性和健壯性的原因總是要使用泛型莹弊。同時,使用泛型還可以避免運行時的ClassCastException涡尘。
- 使用JDK提供的不變類(immutable class)作為Map的鍵可以避免為我們自己的類實現(xiàn)hashCode()和equals()方法忍弛。
- 編程的時候接口優(yōu)于實現(xiàn)。
- 底層的集合實際上是空的情況下考抄,返回長度是0的集合或者是數(shù)組细疚,不要返回null。
Enumeration接口和Iterator接口的區(qū)別有哪些川梅?
Enumeration速度是Iterator的2倍疯兼,同時占用更少的內(nèi)存。但是挑势,Iterator遠遠比Enumeration安全镇防,因為其他線程不能夠修改正在被iterator遍歷的集合里面的對象。同時潮饱,Iterator允許調(diào)用者刪除底層集合里面的元素来氧,這對Enumeration來說是不可能的。
- HashSet和TreeSet有什么區(qū)別?
HashSet是由一個hash表來實現(xiàn)的啦扬,因此中狂,它的元素是無序的。add()扑毡,remove()胃榕,contains()方法的時間復(fù)雜度是O(1)。
另一方面瞄摊,TreeSet是由一個樹形的結(jié)構(gòu)來實現(xiàn)的勋又,它里面的元素是有序的。因此换帜,add()楔壤,remove(),contains()方法的時間復(fù)雜度是O(logn)惯驼。
垃圾收集器(Garbage Collectors)
- Java中垃圾回收有什么目的蹲嚣?什么時候進行垃圾回收?
垃圾回收的目的是識別并且丟棄應(yīng)用不再使用的對象來釋放和重用資源祟牲。
- System.gc()和Runtime.gc()會做什么事情隙畜?
這兩個方法用來提示JVM要進行垃圾回收。但是说贝,立即開始還是延遲進行垃圾回收是取決于JVM的议惰。
- finalize()方法什么時候被調(diào)用?析構(gòu)函數(shù)(finalization)的目的是什么狂丝?
在釋放對象占用的內(nèi)存之前换淆,垃圾收集器會調(diào)用對象的finalize()方法。一般建議在該方法中釋放對象持有的資源几颜。
- 如果對象的引用被置為null,垃圾收集器是否會立即釋放對象占用的內(nèi)存讯屈?
不會蛋哭,在下一個垃圾回收周期中,這個對象將是可被回收的涮母。
- Java堆的結(jié)構(gòu)是什么樣子的谆趾?什么是堆中的永久代(Perm Gen space)?
JVM的堆是運行時數(shù)據(jù)區(qū),所有類的實例和數(shù)組都是在堆上分配內(nèi)存叛本。它在JVM啟動的時候被創(chuàng)建沪蓬。對象所占的堆內(nèi)存是由自動內(nèi)存管理系統(tǒng)也就是垃圾收集器回收。
堆內(nèi)存是由存活和死亡的對象組成的来候。存活的對象是應(yīng)用可以訪問的跷叉,不會被垃圾回收。死亡的對象是應(yīng)用不可訪問尚且還沒有被垃圾收集器回收掉的對象。一直到垃圾收集器把這些對象回收掉之前云挟,他們會一直占據(jù)堆內(nèi)存空間梆砸。
- 串行(serial)收集器和吞吐量(throughput)收集器的區(qū)別是什么?
吞吐量收集器使用并行版本的新生代垃圾收集器园欣,它用于中等規(guī)模和大規(guī)模數(shù)據(jù)的應(yīng)用程序帖世。而串行收集器對大多數(shù)的小應(yīng)用(在現(xiàn)代處理器上需要大概100M左右的內(nèi)存)就足夠了。
- 在Java中沸枯,對象什么時候可以被垃圾回收日矫?
當對象對當前使用這個對象的應(yīng)用程序變得不可觸及的時候,這個對象就可以被回收了绑榴。
- JVM的永久代中會發(fā)生垃圾回收么哪轿?
垃圾回收不會發(fā)生在永久代,如果永久代滿了或者是超過了臨界值彭沼,會觸發(fā)完全垃圾回收(Full GC)缔逛。如果你仔細查看垃圾收集器的輸出信息,就會發(fā)現(xiàn)永久代也是被回收的姓惑。這就是為什么正確的永久代大小對避免Full GC是非常重要的原因褐奴。請參考下Java8:從永久代到元數(shù)據(jù)區(qū)