下面是10道java基礎面試題,后附答案
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名申請、網站空間、營銷軟件、網站建設、富川網站維護、網站推廣。
1.什么是 Java 虛擬機?為什么 Java 被稱作是“平臺無關的編程語言”?
Java 虛擬機是一個可以執行 Java 字節碼的虛擬機進程。Java 源文件被編譯成能被 Java 虛擬機執行的字節碼文件。
Java 被設計成允許應用程序可以運行在任意的平臺,而不需要程序員為每一個平臺單獨重寫或者是重新編譯。Java 虛擬機讓這個變為可能,因為它知道底層硬件平臺的指令長度和其他特性。
2.“static”關鍵字是什么意思?Java 中是否可以覆蓋(override)一個 private 或者是static 的方法?
“static”關鍵字表明一個成員變量或者是成員方法可以在沒有所屬的類的實例變量的情況下被訪問。
Java 中 static 方法不能被覆蓋,因為方法覆蓋是基于運行時動態綁定的,而 static 方法是編譯時靜態綁定的。static 方法跟類的任何實例都不相關,所以概念上不適用。
3.JDK 和 JRE 的區別是什么?
Java 運行時環境(JRE)是將要執行 Java 程序的 Java 虛擬機。它同時也包含了執行 applet 需要的瀏覽器插件。Java 開發工具包 (JDK)是完整的 Java 軟件開發包,包含了 JRE,編譯器和其他的工具(比如:JavaDoc,Java 調試器),可以讓開發者開發、編譯、執行 Java 應用程序。
4.是否可以在 static 環境中訪問非 static 變量?
static 變量在 Java 中是屬于類的,它在所有的實例中的值是一樣的。當類被 Java 虛擬機載入的時候,會對 static 變量進行初始化。如果你的代碼嘗試不用實例來訪問非 static 的變量,編譯器會報錯,因為這些變量還沒有被創建出來,還沒有跟任何實例關聯上。
5.Java 支持的數據類型有哪些?什么是自動拆裝箱?
Java 語言支持的 8 中基本數據類型是:
?byte
?short
?int
?long
?float
?double
?boolean
?char
自動裝箱是 Java 編譯器在基本數據類型和對應的對象包裝類型之間做的一個轉化。比如:把 int 轉化成 Integer,double 轉化成 double,等等。反之就是自動拆箱。
6.Java 支持多繼承么?
不支持,Java 不支持多繼承。每個類都只能繼承一個類,但是可以實現多個接口。
7.Java 中,什么是構造函數?什么是構造函數重載?什么是復制構造函數?
當新對象被創建的時候,構造函數會被調用。每一個類都有構造函數。在程序員沒有給類提供構造函數的情況下,Java 編譯器會為這個類創建一個默認的構造函數。
Java 中構造函數重載和方法重載很相似。可以為一個類創建多個構造函數。每一個構造函數必須有它自己唯一的參數列表。
Java 不支持像 C++中那樣的復制構造函數,這個不同點是因為如果你不自己寫構造函數的情況下,Java 不會創建默認的復制構造函數。
8.Java 中的方法覆蓋(Overriding)和方法重載(Overloading)是什么意思?
Java 中的方法重載發生在同一個類里面兩個或者是多個方法的方法名相同但是參數不同的情況。與此相對,方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,參數列表和返回類型。覆蓋者可能不會限制它所覆蓋的方法的訪問。
9.接口和抽象類的區別是什么?
Java 提供和支持創建抽象類和接口。它們的實現有共同點,不同點在于:
?接口中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
?類可以實現很多個接口,但是只能繼承一個抽象類
?類如果要實現一個接口,它必須要實現接口聲明的所有方法。但是,類可以不實現抽象類聲明的所有方法,當然,在這種情況下,類也必須得聲明成是抽象的。
?抽象類可以在不提供接口方法實現的情況下實現接口。
?Java 接口中聲明的變量默認都是 final 的。抽象類可以包含非 final 的變量。
?Java 接口中的成員函數默認是 public 的。抽象類的成員函數可以是 private, protected 或者是 public。
?接口是絕對抽象的,不可以被實例化。抽象類也不可以被實例化,但是,如果它包含 main 方法的話是可以被調用的。
10.什么是值傳遞和引用傳遞?
對象被值傳遞,意味著傳遞了對象的一個副本。因此,就算是改變了對象副本,也不會影響源對象的值。
對象被引用傳遞,意味著傳遞的并不是實際的對象,而是對象的引用。因此,外部對引用對象所做的改變會反映到所有的對象上。
最后祝你面試順利!
不論是物理機還是虛擬機,大部分的程序代碼從開始編譯到最終轉化成物理機的目標代碼或虛擬機能執行的指令集之前,都會按照如下圖所示的各個步驟進行:
其中綠色的模塊可以選擇性實現。很容易看出,上圖中間的那條分支是解釋執行的過程(即一條字節碼一條字節碼地解釋執行,如JavaScript),而下面的那條分支就是傳統編譯原理中從源代碼到目標機器代碼的生成過程。
如今,基于物理機、虛擬機等的語言,大多都遵循這種基于現代經典編譯原理的思路,在執行前先對程序源碼進行詞法解析和語法解析處理,把源碼轉化為抽象語法樹。對于一門具體語言的實現來說,詞法和語法分析乃至后面的優化器和目標代碼生成器都可以選擇獨立于執行引擎,形成一個完整意義的編譯器去實現,這類代表是C/C++語言。也可以把抽象語法樹或指令流之前的步驟實現一個半獨立的編譯器,這類代表是Java語言。又或者可以把這些步驟和執行引擎全部集中在一起實現,如大多數的JavaScript執行器。
Javac編譯
在Java中提到“編譯”,自然很容易想到Javac編譯器將*.java文件編譯成為*.class文件的過程,這里的Javac編譯器稱為前端編譯器,其他的前端編譯器還有諸如Eclipse?JDT中的增量式編譯器ECJ等。相對應的還有后端編譯器,它在程序運行期間將字節碼轉變成機器碼(現在的Java程序在運行時基本都是解釋執行加編譯執行),如HotSpot虛擬機自帶的JIT(Just?In?Time?Compiler)編譯器(分Client端和Server端)。另外,有時候還有可能會碰到靜態提前編譯器(AOT,Ahead?Of?Time?Compiler)直接把*.java文件編譯成本地機器代碼,如GCJ、Excelsior?JET等,這類編譯器我們應該比較少遇到。
下面簡要說下Javac編譯(前端編譯)的過程。
詞法、語法分析
詞法分析是將源代碼的字符流轉變為標記(Token)集合。單個字符是程序編寫過程中的的最小元素,而標記則是編譯過程的最小元素,關鍵字、變量名、字面量、運算符等都可以成為標記,比如整型標志int由三個字符構成,但是它只是一個標記,不可拆分。
語法分析是根據Token序列來構造抽象語法樹的過程。抽象語法樹是一種用來描述程序代碼語法結構的樹形表示方式,語法樹的每一個節點都代表著程序代碼中的一個語法結構,如bao、類型、修飾符、運算符等。經過這個步驟后,編譯器就基本不會再對源碼文件進行操作了,后續的操作都建立在抽象語法樹之上。
填充符號表
完成了語法分析和詞法分析之后,下一步就是填充符號表的過程。符號表是由一組符號地址和符號信息構成的表格。符號表中所登記的信息在編譯的不同階段都要用到,在語義分析(后面的步驟)中,符號表所登記的內容將用于語義檢查和產生中間代碼,在目標代碼生成階段,黨對符號名進行地址分配時,符號表是地址分配的依據。
語義分析
語法樹能表示一個結構正確的源程序的抽象,但無法保證源程序是符合邏輯的。而語義分析的主要任務是讀結構上正確的源程序進行上下文有關性質的審查。語義分析過程分為標注檢查和數據及控制流分析兩個步驟:
標注檢查步驟檢查的內容包括諸如變量使用前是否已被聲明、變量和賦值之間的數據類型是否匹配等。
數據及控制流分析是對程序上下文邏輯更進一步的驗證,它可以檢查出諸如程序局部變量在使用前是否有賦值、方法的每條路徑是否都有返回值、是否所有的受查異常都被正確處理了等問題。
字節碼生成
字節碼生成是Javac編譯過程的最后一個階段。字節碼生成階段不僅僅是把前面各個步驟所生成的信息轉化成字節碼寫到磁盤中,編譯器還進行了少量的代碼添加和轉換工作。?實例構造器init()方法和類構造器clinit()方法就是在這個階段添加到語法樹之中的(這里的實例構造器并不是指默認的構造函數,而是指我們自己重載的構造函數,如果用戶代碼中沒有提供任何構造函數,那編譯器會自動添加一個沒有參數、訪問權限與當前類一致的默認構造函數,這個工作在填充符號表階段就已經完成了)。
JIT編譯
Java程序最初是僅僅通過解釋器解釋執行的,即對字節碼逐條解釋執行,這種方式的執行速度相對會比較慢,尤其當某個方法或代碼塊運行的特別頻繁時,這種方式的執行效率就顯得很低。于是后來在虛擬機中引入了JIT編譯器(即時編譯器),當虛擬機發現某個方法或代碼塊運行特別頻繁時,就會把這些代碼認定為“Hot?Spot?Code”(熱點代碼),為了提高熱點代碼的執行效率,在運行時,虛擬機將會把這些代碼編譯成與本地平臺相關的機器碼,并進行各層次的優化,完成這項任務的正是JIT編譯器。
現在主流的商用虛擬機(如Sun?HotSpot、IBM?J9)中幾乎都同時包含解釋器和編譯器(三大商用虛擬機之一的JRockit是個例外,它內部沒有解釋器,因此會有啟動相應時間長之類的缺點,但它主要是面向服務端的應用,這類應用一般不會重點關注啟動時間)。二者各有優勢:當程序需要迅速啟動和執行時,解釋器可以首先發揮作用,省去編譯的時間,立即執行;當程序運行后,隨著時間的推移,編譯器逐漸會返回作用,把越來越多的代碼編譯成本地代碼后,可以獲取更高的執行效率。解釋執行可以節約內存,而編譯執行可以提升效率。
HotSpot虛擬機中內置了兩個JIT編譯器:Client?Complier和Server?Complier,分別用在客戶端和服務端,目前主流的HotSpot虛擬機中默認是采用解釋器與其中一個編譯器直接配合的方式工作。
運行過程中會被即時編譯器編譯的“熱點代碼”有兩類:
被多次調用的方法。
被多次調用的循環體。
兩種情況,編譯器都是以整個方法作為編譯對象,這種編譯也是虛擬機中標準的編譯方式。要知道一段代碼或方法是不是熱點代碼,是不是需要觸發即時編譯,需要進行Hot?Spot?Detection(熱點探測)。目前主要的熱點?判定方式有以下兩種:
基于采樣的熱點探測:采用這種方法的虛擬機會周期性地檢查各個線程的棧頂,如果發現某些方法經常出現在棧頂,那這段方法代碼就是“熱點代碼”。這種探測方法的好處是實現簡單高效,還可以很容易地獲取方法調用關系,缺點是很難精確地確認一個方法的熱度,容易因為受到線程阻塞或別的外界因素的影響而擾亂熱點探測。
基于計數器的熱點探測:采用這種方法的虛擬機會為每個方法,甚至是代碼塊建立計數器,統計方法的執行次數,如果執行次數超過一定的閥值,就認為它是“熱點方法”。這種統計方法實現復雜一些,需要為每個方法建立并維護計數器,而且不能直接獲取到方法的調用關系,但是它的統計結果相對更加精確嚴謹。
在HotSpot虛擬機中使用的是第二種——基于計數器的熱點探測方法,因此它為每個方法準備了兩個計數器:方法調用計數器和回邊計數器。
方法調用計數器用來統計方法調用的次數,在默認設置下,方法調用計數器統計的并不是方法被調用的絕對次數,而是一個相對的執行頻率,即一段時間內方法被調用的次數。
回邊計數器用于統計一個方法中循環體代碼執行的次數(準確地說,應該是回邊的次數,因為并非所有的循環都是回邊),在字節碼中遇到控制流向后跳轉的指令就稱為“回邊”。
在確定虛擬機運行參數的前提下,這兩個計數器都有一個確定的閥值,當計數器的值超過了閥值,就會觸發JIT編譯。觸發了JIT編譯后,在默認設置下,執行引擎并不會同步等待編譯請求完成,而是繼續進入解釋器按照解釋方式執行字節碼,直到提交的請求被編譯器編譯完成為止(編譯工作在后臺線程中進行)。當編譯工作完成后,下一次調用該方法或代碼時,就會使用已編譯的版本。
由于方法計數器觸發即時編譯的過程與回邊計數器觸發即時編譯的過程類似,因此這里僅給出方法調用計數器觸發即時編譯的流程:
以下從技術角度就常見的保護措施 和常用工具來看看如何有效保護java代碼:1. 將java包裝成exe 特點:將jar包裝成可執行文件,便于使用,但對java程序沒有任何保護。不要以為生成了exe就和普通可執行文件效果一樣了。這些包裝成exe的程序運行時都會將jar文件釋放到臨時目錄,很容易獲取。常用的工具有exe4j、jsmooth、NativeJ等等。jsmooth生成的exe運行時臨時目錄在exe所在目錄中或是用戶臨時目錄 中;exe4j生成的exe運行時臨時目錄在用戶臨時目錄中;NativeJ生成的exe直接用winrar打開,然后用zip格式修復成一個jar文件,就得到了原文件。如果只是為了使用和發布方便,不需要保護java代碼,使用這些工具是很好的選擇。2. java混淆器特點:使用一種或多種處理方式將class文件、java源代碼進行混淆處理后生成新的class,使混淆后的代碼不易被反編譯,而反編譯后的代碼難以閱 讀和理解。這類混淆器工具很多,而且也很有成效。缺點:雖然混淆的代碼反編譯后不易讀懂,但對于有經驗的人或是多花些時間,還是能找到或計算出你代碼中隱藏的敏感內容,而且在很多應用中不是全部代碼都能混淆的,往往一些關鍵的庫、類名、方法名、變量名等因使用要求的限制反而還不能混淆。3. 隔離java程序到服務端特點:把java程序放到服務端,讓用戶不能訪問到class文件和相關配套文件,客戶端只通過接口訪問。這種方式在客戶/服務模式的應用中能較好地保護java代碼。缺點是:必須是客戶/服務模式,這種特點限制了此種方式的使用范圍;客戶端因為邏輯的暴露始終是較為薄弱的環節,所以訪問接口時一般都需要安全性認證。4. java加密保護特點:自定義ClassLoader,將class文件和相關文件加密,運行時由此ClassLoader解密相關文件并裝載類,要起到保護作用必須自定 義本地代碼執行器將自定義ClassLoader和加密解密的相關類和配套文件也保護起來。此種方式能很有效地保護java代碼。缺點:可以通過替換JRE包中與類裝載相關的java類或虛擬機動態庫截獲java字節碼。 jar2exe屬于這類工具。5. 提前編譯技術(AOT) 特點:將java代碼靜態編譯成本地機器碼,脫離通用JRE。此種方式能夠非常有效地保護java代碼,且程序啟動比通用JVM快一點。具有代表性的是GNU的gcj,可以做到對java代碼完全提前編譯,但gcj存在諸多局限性,如:對JRE 5不能完整支持、不支持JRE 6及以后的版本。由于java平臺的復雜性,做到能及時支持最新java版本和JRE的完全提前編譯是非常困難的,所以這類工具往往采取靈活方式,該用即時編譯的地方還是 要用,成為提前編譯和即時編譯的混合體。缺點:由于與通用JRE的差異和java運用中的復雜性,并非java程序中的所有jar都能得到完全的保護;只能使用此種工具提供的一個運行環境,如果工具更新滯后或你需要特定版本的JRE,有可能得不到此種工具的支持。 Excelsior JET屬于這類工具。6. 使用jni方式保護特點:將敏感的方法和數據通過jni方式處理。此種方式和“隔離java程序到服務端”有些類似,可以看作把需要保護的代碼和數據“隔離”到動態庫中,不同的是可以在單機程序中運用。缺點和上述“隔離java程序到服務端”類似。7. 不脫離JRE的綜合方式保護特點:非提前編譯,不脫離JRE,采用多種軟保護方式,從多方面防止java程序被竊取。此種方式由于采取了多種保護措施,比如自定義執行器和裝載器、加密、JNI、安全性檢測、生成可執行文件等等,使保護力度大大增強,同樣能夠非常有效地保護java代碼。缺點:由于jar文件存在方式的改變和java運用中的復雜性,并非java程序中的所有jar都能得到完全的保護;很有可能并不支持所有的JRE版本。 JXMaker屬于此類工具。8. 用加密鎖硬件保護特點:使用與硬件相關的專用程序將java虛擬機啟動程序加殼,將虛擬機配套文件和java程序加密,啟動的是加殼程序,由加殼程序建立一個與硬件相關的 受保護的運行環境,為了加強安全性可以和加密鎖內植入的程序互動。此種方式與以上“不脫離JRE的綜合方式保護”相似,只是使用了專用硬件設備,也能很好地保護java代碼。缺點:有人認為加密鎖用戶使用上不太方便,且每個安裝需要附帶一個。從以上描述中我們可以看出:1. 各種保護方式都有其優缺點,應根據實際選用2. 要更好地保護java代碼應該使用綜合的保護措施3. 單機環境中要真正有效保護java代碼,必須要有本地代碼程序配合當然,安全都是相對的,一方面看你的保護措施和使用的工具能達到的程度,一方面看黑客的意愿和能力,不能只從技術上保護知識產權??傊?,在java 代碼保護方面可以采取各種可能的方式,不可拘泥于那些條條框框。
文章標題:java源代碼進行aot java iterator源碼
文章出自:http://m.newbst.com/article22/doppjcc.html
成都網站建設公司_創新互聯,為您提供虛擬主機、響應式網站、自適應網站、外貿建站、建站公司、做網站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯