這是我在准備Java考試時整理的提綱,如果是通過搜索引擎搜索到這篇博客的師弟師妹,建議還是先參照PPT和課本,這個大綱也不是很准確,自己總結會更有收獲,多去理解含義,不要死記硬背,否則遇到概念辨析題會特別吃虧,如果覺得有收獲點贊關注,祝考試順利。
1.Java語言具有可移植性、可跨平台運行特點的原因是什么?
可移植性:因為 Java 是結構中立的,所以Java 的程序是可移植的。 他們可以不經過重新編譯而在任何一個機器上運行。
可跨平台:Java語言是高級語言,而Java字節碼是低級語言,字節碼類似於機器指令,但它是體系結構中立的,是可以在任何帶Java虛擬機(JVM)的平台上運行的。虛擬機不是物理機器,而是一個解釋Java字節碼的程序。這樣Java字節碼可以在不同的硬件平台和操作系統上運行。Java源代碼編譯成Java字節碼,然后Java字節碼被JVM解釋執行。
2.為什么說Java語言具有健壯、安全的特性?
健壯性:
Java 編譯器檢測出許多別的語言只有在首次執行的時候才會指出的問題。
Java 已經清除了幾種在其它語言中被發現易於出錯的編程結構。
Java具有運行時異常處理特性,它為健壯性提供了編程支持。
安全性:
Java 實現了幾種安全機制以保護系統免受危險程序的破壞 。
當加載某類后,JVM使用一個字節碼驗證器(bytecode verifier)的程序來檢驗字節碼的合法性,確保字節碼不會違反Java的安全規范。Java強制執行嚴格的安全規范,以確保來自網絡的Java程序不會篡改和危害你的計算機。
3.簡述Java虛擬機(JVM)的作用是什么?
Java虛擬機:是一個解釋執行Java字節碼的軟件。
4.簡述JVM的垃圾回收機制。
在C++中,使用new實現動態內存分配,分配后需要負責這塊內存的整個生命周期,最后由delete來釋放,但如果忘記釋放內容,會導致內存泄露。同時錯誤的使用delete可能會清除尚未引用的對象或空間中的公共資源。
在Java中,使用new來創建對象並在堆中為對象分配空間(基本數據類型除外),而對象的釋放則是由GC(Garbage Collection垃圾回收器)決定和執行。Java中對內存對象的訪問采用的是引用方式,當CG跟蹤到某個對象沒有被任何線程訪問時,該對象就要被刪除,就將其加入垃圾回收隊列,但是進行垃圾回收的線程是一種低優先級的系統線程,為此系統不會馬上進行對象的消除,因而何時消除並釋放內存是無法預知的。
一般是在CPU空閑或空間不足時自動進行垃圾回收,程序員無法精准掌握控制垃圾回收的時機和回收的順序。
5.簡述軟件開發的過程。(書,PPT)
需求規范、系統分析、系統設計、實現、測試、部署、維護。
6.什么是短路運算符“(short-circuit operator)?試舉例說明。
短路運算符:顧名思義,短路運算符具有短路功能.
如果 "&&" 運算符的第一個表達式為false,則第二個表達式就不會執行
如果 "||" 運算符的第一個表達式為true,則第二個表達式就不會執行
If x is 1, what is x after this expression?
(x > 1)&& (x++ < 10)
If x is 1, what is x after this expression?
(1 > x) && ( 1 > x++)
7.簡述使用JDK中的調試工具jdb時,可以使用的調試方法。
JDK包含了一個命令行調試器jdb,結合一個類名來調用該命令。Jdb本身也是一個Java程序,運行自身的一個Java解釋器的拷貝。
Debugger is a program that facilitates debugging. You can use a debugger to
一次執行一條語句
跟蹤進入或者一步運行一個方法
設置斷點
顯示變量
顯示調用堆棧
修改變量
8.什么是Unicode編碼?(書,PPT)
Unicode編碼是Unicode協會建立的一種編碼方案,它支持使用世界各種語言所書寫的文本交換、處理和顯示。Unicode編碼一開始被設計為16位的字符編碼,但一個16位的編碼所能產生的字符只用65535個,它不足以表示全世界所有字符的,因此Unicode標准被擴展為1112064個字符。這些字符都遠超原來16位的限制被稱為補充字符(supplementary character)。Java支持這些補充字符。
一個16位的Unicode編碼占兩個字節,用以\u開頭的4位十六進制數表示,范圍從'\u0000'到'\uFFFF'。
9.什么是方法簽名(Method signature)?試舉例說明。(書,PPT)
方法簽名( Method signature ):包括方法名和參數列表。
注意方法名不包括方法的返回類型、返回值和訪問修飾符。
Max(int num1, int mum2)
10.Java語言中,方法的參數傳遞有哪幾種?不同類型參數傳傳遞的區別是什么。試舉例說明。
值傳遞
引用傳遞
值傳遞:方法調用時,實際參數把它的值傳遞給對應的形式參數,方法執行中形式參數,形式值的改變不影響實際參數的值。
引用傳遞:也稱為傳地址。方法調用時,實際參數的引用(地址,而不是參數的值)傳遞給方法中相對應的形式參數,在方法執行中,對形式參數的操作實際上就是對實際參數的操作,方法執行中形式參數值的改變將會影響實際參數的值。
值傳遞例子:
引用傳遞例子:
Java使用值傳遞的方法傳遞實參給方法。傳遞基本數據類型的值和傳遞數組值會有很大不同。
對於基本數據類型參數,傳遞的是實參的值。在方法中改變局部參數的值並不影響方法之外變量的值。
對於數組類型參數,參數值是數組的引用,傳遞給方法的是這個引用。方法體中數組發生的改變,將會影響到作為參數傳給方法的原始數組。
11.什么是局部變量?什么是局部變量的作用域?可不可以在一個方法聲明名字相同的變量多次?局部變量的初始化與實例變量的初始化有什么異同?
局部變量:在方法中定義的變量是局部變量(local variable)。
局部變量的作用域:從聲明的地方開始,知道包含該變量的塊結束為止。局部變量都必須在使用之前進行聲明和賦值。
你可以在一個方法的不同塊里聲明相同的變量多次, 但是不能在嵌套塊或同一塊中兩次聲明同一變量。
局部變量的初始化與實例變量的初始化的異同:
實例變量是聲明在類里面而不是在方法中。局部變量是聲明在方法中的。
實例變量永遠都有默認值;如果你沒有明確的賦值給實例變量,實例變量還是會有值。
局部變量沒有默認值;如果在局部變量被初始化前就要使用的話,編譯器會顯示錯誤。局部變量都必須在使用之前進行聲明。
12.如何聲明一個數組引用變量,如何創建一個數組?什么時候為數組分配內存?什么是數組的越界訪問?怎樣避免下標越界?
聲明數組變量datatype[] arrayRefVar;
double[] myList; double myList[];// 這種風格是允許的,但不推薦使用
創建數組arrayRefVar = new datatype[arraySize];
myList = new double[10];
// 創建數組並將它的引用賦值給變量
refVar = new dataType[10][10];
//聲明和創建數組合放在一條語句中
dataType[][] refVar = new dataType[10][10];
//還可選擇的語法
dataType refVar[][] = new dataType[10][10];
你也可以使用數組初始化語法來聲明、創建和初始化一個二維數組。例如:
Java中的數組可以看到一個特殊的對象,聲明時是放在棧中的,分配的空間存儲在堆中
當數組被初始化時給數組分配空間
數組的越界訪問:數組(指針)越界訪問,是指使用了超過有效范圍的偏移量。
如只分配了10個元素的空間,但是訪問了第11個元素,就屬於越界。
避免下標越界的方法:
為了避免錯誤的發生,在使用時應確保所使用的下標不超過arrayRefVar.length-1,且不小於0
在Java中,數組被看做對象。數組是用new操作符創建的,一個數組變量實際上是包含一個數組引用的變量。
13.什么是不規則數組(ragged array,鋸齒數組),試舉例說明。
二維數組中的每一行本身就是一個數組。因此,各行的長度可以不同。這樣的數組被稱為鋸齒數組。例如:
int[][] matrix = { {1, 2, 3, 4, 5}, {2, 3, 4, 5}, {3, 4, 5}, {4, 5}, {5} };
matrix.length 是 5
matrix[0].length 是 5
matrix[1].length 是 4
matrix[2].length 是 3
matrix[3].length 是 2
matrix[4].length 是 1
一定要注意二維數組的最后一行后面沒有逗號
14.什么是構造方法?構造方法有返回值嗎?構造方法如何命名?構造方法可以重載嗎?什么是缺省構造方法(default constructor,默認構造方法)?什么情況下,系統才會自動給一個類提供缺省構造方法?
構造方法是一種特殊的方法,調用它來初始化對象。
構造方法沒有返回值,沒有void。
構造方法必須具備和它所屬類相同的名字。
構造方法以重載。也就是說可以有同名的構造方法, 但他們必須有不同的函數簽名。
默認構造方法:如果一個類中沒有構造方法,類中隱式地定義的一個方法體為空的無參構造方法。
當且僅當類中沒有明確定義任何構造方法時系統才會自動提供它。
15.操作符new的作用是什么?構造方法的作用是什么?什么時候會被調用?構方法的執行順序是什么(父類與子類的構造方法)?
new運算符實例化一個類對象,通過給這個對象分配內存並返回一個指向該內存的引用。new運算符也調用了對象的構造函數。
構造方法是一種特殊的方法,主要用來在創建對象時初始化對象,即為對象成員變量賦初始值。
構造方法是在使用new操作符創建一個對象(僅此一種情況)時被自動調用的。
先調用父類的構造方法,再調用子類的構造方法。
16.什么是引用類型?試舉例畫圖說明基本類型變量和引用類型變量的區別。試舉例說明基本類型變量的復制操作(=)和對象類型變量的復制操作(=)有何不同。
類是一種引用類型,這意味着該類類型的變量可以引用該類的一個實例。
Circle mycircle = new Circle();
mycircle 中存放的是對Circle對象的引用。
基本類型變量和引用類型變量的區別:
對基本類型變量來說,對應內存所存儲的值是基本數據類型的值;對應引用類型變量來說,對應內存所存儲的值是一個引用,是對象的存儲地址。
如圖所示,int類型變量i的值就是int值1,而Circle對象c的值保存的是一個引用,它只用Circle對象的內容存儲在內存中的位置。
將一個變量賦值給另一個變量時,另外一個變量就被賦值給相同的值,對於基本數據類型而言,就是將一個變量的值賦給另一個變量。對於引用數據類型而言,就是將一個變量的引用賦給另一個變量。
注意在執行完賦值語句c1=c2后,c1指向c2所指的同一個對象,c1以前引用的對象就不再有用,會變成垃圾進行回收。
17.什么是實例變量、實例方法、靜態變量、靜態方法。調用實例方法與靜態方法有何異同。靜態變量的作用域是什么?
實例變量依賴於類的某個具體的實例,它是不能被同一個類的不同對象所共享的。存儲在互不相關的內存中。
實例方法被類的實例調用的方法。
靜態變量(static variable)被類中的所有對象所共享。也成為類(class variable)變量。作用域是整個類。
靜態方法(static method)。無須創建類的實例就可以調用的方法。
使用靜態修飾符static聲明靜態變量、常量和方法。
實例方法與靜態方法異同:實例方法可以調用實例方法和靜態方法,以及訪問實例數據域或者靜態數據域。靜態方法只能調用靜態方法以及訪問靜態數據域,不能調用實例方法或者訪問實例數據域,因為靜態方法和靜態數據域不屬於某個特定的對象。實例方法必須創建實例才能調用,靜態方法無需創建實例就可以調用。
靜態變量的作用域:整個類的所有對象。作用域為類級。
18.java中,當類的成員前用private、protected、public、默認(成員前無任何修飾符)修飾時,成員的可訪問性分別是什么?
Private:私有的,只能在它自己的類中被訪問。數據或方法可以被聲明它的類訪問。
Public:公有的,都可以訪問。類、數據或方法對在任何包中的任何類都是可見的。
Protected:受保護的,包內都可見,其他包內的子類也可見。允許子類訪問定義在父類中的數據域或方法,但不允許不同包的非子類訪問這些數據域和方法;
默認:僅包內可見,類、變量或者方法能被同一個包(package)內的任何一個訪問。
19.什么是不可變類(Immutable Classes)、不可變對象(Immutable Objects)?以String為例,說明不可變類的優點?
不可變對象:一旦創建其內容就不能再改變
不可變類:不可變對象的類稱為不可變類
成為不可變類需要滿足的條件:
a、所有數據域都是私有的
b、沒有修改器方法
c、沒有返回一個指向可變數據域的引用的訪問器方法
以String為例,說明不可變類的優點:
a、便於實現字符串常量池
b、使多線程安全
c、避免安全問題。網絡連接和數據庫連接使用字符串做參數,字符串不可變
d、加快字符串處理速度
20.簡述類的下述設計原則:內聚性、分擔責任、重用、一致性、清晰性、封裝性。
(1)(內聚性)類應該描述一個單一實體,而所有的類操作應該在邏輯上互相配合,支持一個一致的目的。例如:可以設計一個類用於學生,但不應該將學生與教職工組合在同一個類中,因為學生和教職工是不同的實體。
(2)(分擔責任) 如果一個實體擔負太多的職責,就應該按各自的職責將它分為幾個類。例如:String類、StringBuffer類和StringBuilder類都用於處理字符串,但是它們的職責各有不同。String類處理不可變字符串,StringBuilder類創建可變字符串,StringBuffer和StringBuilder類似,只是StringBuffer類還包括更新字符串的同步方法。
(3)類是為了重用而設計的。用戶可以以不同的組合和順序,在許多不同環境中合並多個類。因此,應該設計一個類,這個類應該沒有對用戶使用它的目的及使用時間的限制,設計屬性以確保用戶可以按值的任何順序和任何組合來設置屬性,所設計的方法實現的功能應該與它們出現的順序無關。
(4)一致性:遵循標准Java程序設計風格和命名習慣。為類、數據域和方法選取具有信息的名字。通常的風格是將數據聲明置於構造方法之前,並且將構造方法置於方法之前。
(5)清晰性:類應該有一個很清晰的合約,從而易於解釋和理解。用戶可以以各種不同組合、順序,以及在各種環境中結合使用多個類。因此再設計一個類時,這個類不應該限制用戶如何以及何時使用該類;以一種方式設計屬性,以容許用戶按值的任何順序和任何組合來設置;設計方法應該使得實現的功能與他們出現的順序無關。
方法應在不產生混淆的情況下進行直觀定義。不應該聲明一個來自其他數據域的數據域。
(6)封裝性:一個類應該使用private修飾符隱藏其數據,以免用戶直接訪問它。這使得類更易於維護。只在希望數據域可讀的情況下,才提供get方法;也只在希望數據域可更新的情況下,才提供set方法。
21.什么是關聯?什么是聚集?什么是組合?聚集和組合的UML圖標識是什么?
關聯:關聯是一種常見的二元關系,描述兩個類之間的活動。
聚集:聚合關系強調的是整體和部分的關系,其中部分可以脫離整體而存在。比如雁群和一只大雁的關系,就是聚合關系,大雁離開雁群還是可以獨立存在的。
組合:組合關系也是一種特殊的關聯關系,它與聚合關系很像,也是強調整體與部分的關系,不同的是部分無法脫離整體存在。比如學生用手撿錢,其中手就是學生的一部分,但是手不能脫離學生而單獨存在。
22.簡述生成子類對象時,如何調用父類的構造方法?
父類的構造方法不能被繼承。
它們被顯式(explicitly)或隱式(implicitly)地調用。
使用super關鍵字顯式調用。
public Circle(double radius, String color, boolean filled) { super(color, filled); this.radius = radius; }
23.什么是構造方法鏈?關鍵字super的作用是什么?使用super時應注意什么?
當構造一個子類的對象時,子類構造方法會在完成自己的任務之前,首先調用它的父類的構造方法。如果父類繼承自其他類,那么父類構造方法又會在完成自己的任務之前,調用它自己的父類的構造方法。這個過程持續到沿着這個繼承體系結構的最后一個構造方法被調用為止。這就是構造方法鏈。構造一個類的實例時,將會調用沿着繼承鏈的所有父類的構造方法。這就被稱為構造方法鏈(constructor chaining)。
super的作用:1)調用父類的構造方法 2)調用父類的普通方法
語句super()調用父類的無參構造方法,而語句super(arguments)調用與參數匹配的父類的構造方法。語句super()和super(arguments)必須出現在子類構造方法的第一行,這是顯示調用父類構造方法的唯一方式。
調用父類的普通方法
public void printCircle() { System.out.println("The circle is created " + super.getDateCreated() + " and the radius is " + radius); }
在這種情況下其實沒必要加super,因為該方法已經被circle繼承,但在某些情況下必不可少。
使用super時應注意:
調用父類構造方法必須使用關鍵字super,而這個調用必須是構造方法的第一條語句!在子類中調用父類構造方法的名字會引起一個語法錯誤。
24.java中,什么是方法覆蓋?什么是方法重載?試比較覆蓋與重載?java中的重載與C++的重載有何不同。試舉例說明。
方法覆蓋:子類從父類中繼承方法,有時,子類需要修改父類中定義的方法的實現,這個操作被稱作方法覆蓋(重寫)。
方法重載:如果有兩個方法的方法名相同,但參數不一致,那么可以說一個方法是另一個方法的重載。
比較:方法重載意味着使用同樣的名字但是不同的簽名來定義多個方法。方法重寫發生在具有繼承關系的不同類中,意味着在子類中提供一個對方法的新的實現。
Java與c++中的不同:Java中方法重載可以發生在同一個類中,也可以發生 在具有繼承關系的不同類中;而C++類中的函數重載只能發生在本類中,這是他們一個非常重要的區別。
25.簡述多態的概念和多態的意義。
一種物質有多種形態。在專業術語中,多態是一種運行時綁定機制(run-time binding) ,也就是使用父類對象的地方都可以使用子類的對象。這就是通常所說的多態。
多態意味着父類型的變量可以引用子類型的對象。
26.什么是引用變量的聲明類型?什么是引用變量的實際類型?什么是動態綁定?
一個變量必須被聲明為某種類型。變量的這個類型稱為它的聲明類型。
變量的實際類型是被該變量引用的對象的實際類型。
動態綁定:在運行時根據具體對象的實際類型進行綁定。
27.父類與子類的引用變量之間,在互相轉換時,轉換規則是什么?instanceof運算符的作用是什么?試舉例說明。
總是可以將一個子類的實例轉換為一個父類的變量,稱為向上轉換,因為子類的實例永遠是它的父類的實例。當把一個父類的實例轉換為它的子類變量(稱為向下轉換)時,必須使用轉換記號“(子類名)”進行顯示轉換,向編譯器表明你的意圖。為使轉換成功,必須確保要轉換的對象是子類的一個實例。如果父類對象不是子類的一個實例,就會出現一個運行異常ClassCastException。
使用instanceof運算符來檢測一個對象是否屬於一個類,例:
Object myObject = new Circle(); ... // Some lines of code /** Perform casting if myObject is an instance of Circle */ if (myObject instanceof Circle) { System.out.println("The circle diameter is " + ((Circle)myObject).getDiameter()); ...}
28.試比較equals方法和比較操作符“==”。
equals方法
1. 是一個方法,而非運算符
2. 只能適用於引用數據類型
3. Object類中equals()的定義:
public boolean equals(Object obj) { return (this == obj); }
說明:Object類中定義的equals()和==的作用是相同的:比較兩個對象的地址值是否相同.即兩個引用是否指向同一個對象實體
4. 像String、Date、File、包裝類等都重寫了Object類中的equals()方法。重寫以后,比較的不是兩個引用的地址是否相同,而是比較兩個對象的"實體內容"是否相同。
5. 通常情況下,我們自定義的類如果使用equals()的話,也通常是比較兩個對象的"實體內容"是否相同。那么,我們 就需要對Object類中的equals()進行重寫.
重寫的原則:比較兩個對象的實體內容是否相同.
比較運算符==
- 如果比較的是基本數據類型變量:比較兩個變量保存的數據是否相等。(不一定類型要相同)
- 如果比較的是引用數據類型變量:比較兩個對象的地址值是否相同.即兩個引用是否指向同一個對象實體
29.什么是this引用變量,其作用是什么?通過this調用同一個類的構造主法時,此語句是否可以出現在構造方法的任意位置上?
關鍵字this是指向調用對象本身的引用名。可以用this關鍵字訪問對象的實例成員。
this作用:
this可以訪問隱藏數據域
this可以調用同一個類的另外一個構造方法
不可以出現在構造方法的任意位置。Java要求在構造方法中,語句this(參數列表)應在其他可執行語句之前出現。
30.簡述final修飾類、變量、方法時,其作用是什么。
final類不能被繼承,例如:final class Math {...}
final變量是一個常量:final static double PI = 3.14159;
父類中的final方法不能被子類所覆蓋(重寫)。
31.定義一個子類時,使用哪一個關鍵字表示繼承?什么是單一繼承?什么是多重繼承?Java支持多重繼承嗎?為了實現類似多重繼承的功能,在java中應該如何做?
關鍵字:extends
一個Java類只可能直接繼承自一個父類。這種限制成為單一繼承。
從幾個類派生出一個子類,這個能力稱為多重繼承。
Java是不允許多重繼承的。
在Java中多重繼承是可以通過接口來實現的。
32.簡述與使用if語句處理異常相比,使用throw-try-catch-finally語句處理異常有什么優點。
if用於邏輯判斷,try運行可能會存在異常的代碼塊,throw拋出異常,catch捕獲異常,finally是一定會執行的代碼,在異常處理中if用於控制程序,不適合錯誤提示及跟蹤錯誤,throw-try-catch-finally語句將檢測錯誤和處理錯誤分離,可以顯示錯誤提示,跟蹤並處理錯誤,正確代碼與錯誤代碼分離,更清晰
33.異常處理的優點和缺點分別是什么?
它能使方法拋出一個異常給它的調用者,並由這個調用者可以處理該異常。如果沒有這個能力,那么被調用的方法就必須自己處理異常或終止該程序。
異常處理最根本的優勢就是將檢測錯誤(由被調用的方法完成)從處理錯誤(由調用方法完成)中分離出來。
缺點:異常處理通常需要更多的時間和資源。
34.簡述異常處理的過程。如何定義一個自定義異常類?關鍵字throw和throws的作用分別是什么?
聲明一個異常、拋出一個異常、捕獲一個異常
異常處理過程:當異常被拋出,正常的執行流程就被中斷了。異常被catch塊捕獲,catch塊中的代碼處理異常。之后,執行catch 塊之后的語句。
可以通過派生java.lang.Exception類來定義一個自定義異常類。
自定義異常類:盡量使用API 中的異常類,如果遇到不能用預定義異常類恰當描述的問題,就可以通過派生exception 類或其子類,來創建自己的異常類。
聲明異常的關鍵字是throws,拋出異常的關鍵字是throw。
關鍵字throw是拋出異常,語句類似於方法的調用,但不同於調用方法的是,它調用catch塊。
關鍵字throws 是聲明異常,表明MethodName 方法可能會拋出異常ExName,如果方法可能會拋出多個異常,就可以用throws后面一個用逗號分隔的異常列表。
35.簡述try{…} catch(…){…}catch(…){…}結構的工作過程。
try用來檢測可能存在異常的代碼塊,如果在執行try塊的過程中沒有異常,則跳過catch子句;如果在執行try塊中某條語句拋出一條異常,正常的執行流程就被中斷了,跳過try塊剩余的語句,異常被對應的catch塊捕獲,catch塊中的代碼處理異常。之后,執行catch 塊之后的語句。
36.什么是是必檢異常(checked exceptions)?什么是非檢查型異常(unchecked exceptions)?
RuntimeException、Error以及它們的子類都被稱為免檢異常(unchecked exceptions)。
剩下所有其它異常都被稱為必檢異常(checked exceptions),意思是編譯器會強制程序員檢查並通過try-catch塊處理它們,或在方法頭進行聲明。
在大多數情況下,免檢異常都會反映出程序設計上不可恢復的邏輯錯誤,這些都是程序中必須糾正的邏輯錯誤。免檢異常可能在程序的任何一個地方出現。為了避免過多地使用try-catch塊,Java語言不強制要求編寫代碼捕獲或聲明免檢異常。
注:unchecked exceptions,譯為“非檢查型異常”更准確些。
37.什么是抽象類型?抽象類的作用是什么?抽象類是否可實例化?
一個父類設計的非常抽象,以至於它都沒有任何具體的實例,這樣的類稱為抽象類。
作用:抽象類可以包含抽象方法,這些方法將在具體的子類中實現。在繼承的層次結構中,每個新子類都使類變得越來越明確和具體。
抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類一樣。
由於抽象類不能實例化對象,所以抽象類必須被繼承,才能被使用。
抽象類不能用new操作符來創建它的實例。
38.接口是什么?接口的作用是什么?如何定義一個接口?如何使用一個接口?接口可不可以實例化?
接口(interface)是一種與類相似的結構,它只包含常量和抽象方法。
接口在許多方面都與抽象類很相似,但是它的目的是指明相關或者不相關類的多個對象的共同行為。
為了區分接口和類,Java采用下面的語法來定義接口:
使用關鍵字implements繼承一個接口。可以使用接口作為引用變量的數據類型或轉換類型的結果等。
不能實例化。
39.什么是淺復制(Shallow Copy)和深復制(Deep Copy)?如何實現深復制?
淺拷貝:只復制當前的對象,對該對象內部的引用(其他類對象作為自己的元素也叫對其他對象的引用)不能復制(在堆內存中從新創建空間,內容相同,但地址不同)。
深拷貝:對對象內部的引用均復制,是創建一個新的實例,並復制實例。不僅要復制對象的所有基本數據類型的成員變量值,還要為所有引用數據類型的成員變量申請存儲空間,並復制每個引用數據類型成員變量所引用的對象,直到該對象可達的所有對象。也就是說,對象進行深拷貝要對整個對象圖進行拷貝!
(1) 通過重寫clone方法來實現深拷貝。每一層的每個對象都進行淺拷貝。為對象圖的每一層的每一個對象都實現Cloneable接口並重寫clone方法,最后在最頂層的類的重寫的clone方法中調用所有的clone方法即可實現深拷貝。
(2) 通過對象序列化實現深拷貝。將對象序列化為字節序列后,默認會將該對象的整個對象圖進行序列化,再通過反序列即可完美地實現深拷貝。
重寫前只能實現淺拷貝的clone方法
重寫后可以實現深拷貝的clone方法
40.從數據成員、構造方法、成員方法三方面對比一下接口與抽象類。
|
數據成員 |
構造方法 |
成員方法 |
抽象類 |
無限制 |
子類通過構造方法鏈調用構造方法,抽象類不能用new操作符實例化 |
無限制 |
接口 |
所有的變量必須是public static final |
沒有構造方法。接口不能用new操作符實例化 |
所有方法必須是公共的抽象public abstract實例方法 |
41.JavaFX中,什么是舞台(Stage), 場景 (Scene), 節點(Nodes)?三者之間的關系是什么?面板(pane)作用是什么?
一個 JavaFX 應用包含三個主要的控件:Stage、Scene 和 Nodes
Stage舞台:一個Stage對象是一個窗體,用於顯示包含了節點的場景。當應用程序啟動的時候,一個稱為主舞台的Stage對象由JVM自動創建。
Scene場景:表示 JavaFX 應用的物理內容。它包含 scene 圖像所有的內容。scene 對象由 javafx.scene 包中的 Scene 類表示。在一個實例中,場景對象只能添加到一個 stage 中。
可以通過 Scene 類來實例化場景。將尺寸(寬和高)和根節點傳入 stage 的構造方法可以控制它的大小。
Nodes節點:節點是可視化組件,比如一個形狀、一個圖像視圖、一個UI組件或者一個面板。
關系:可以認為舞台是一個支持場景的平台,節點如同在場景中演出的演員。
面板的作用:用於容納節點,自動地將節點布局在一個希望的位置和大小。
42.JavaFX中,什么是屬性綁定?有哪兩種屬性綁定?
屬性綁定:可以將一個目標對象和一個源對象綁定。如果源對象中的值改變了,目標對象也將自動改變。
目標對象稱為綁定對象或者綁定屬性,源對象稱為可綁定對象或者可觀察對象。
一個屬性的改變將反映到另一個對象上,反過來也一樣,這稱為雙向綁定。
如果目標和源同時都是綁定屬性和可觀察屬性,它們就可以使用bindBidirectional方法進行雙向綁定。
單向綁定、雙向綁定。
43.描述面板StackPane、FlowPane、GridPane、Borderpane、HBox、VBox的布局特點是什么。
類 |
描述(布局特點) |
Pane |
布局面板的基類,它有getChildren()方法來返回面板的節點列表 |
StackPane |
節點放置在面板中央,並且疊加在其他節點之上 |
FlowPane |
節點以水平方式一行一行放置,或者垂直方式一列一列放置 |
GridPane |
節點放置在一個二維網格的單元格中 |
Borderpane |
將節點放置在頂部、右邊、底部、左邊以及中間區域 |
HBox |
節點放在單行中 |
VBox |
節點放在單列中 |
44.簡述JavaFX中一個事件從觸發到被處理的過程。
Java采用一個基於委托的模型來進行事件處理:一個源對象觸發一個事件,然后一個對該事件感興趣的對象處理它。后者稱為一個對象處理器或者一個事件監聽器。一個對象如果要成為一個源對象上面的事件處理器,需要滿足兩個條件:
45.什么是事件源對象?什么是事件對象?描述兩者之間的關系。
事件源對象:產生一個事件並且觸發它的組件稱為事件源對象,比如一個按鈕是按鈕單擊動作事件的源對象。
事件對象:由事件源產生的對象,是一個事件類的實例,一個事件對象包含與事件相關的任何屬性。
關系:事件是從一個事件源上產生的對象。
46.文本IO與二進制IO有何區別?
文本I/O建立在二進制I/O之上,為字符編碼和解碼提供了一個抽象級別。文本I/O需要進行編碼和解碼。寫入字符時,JVM將Unicode轉化為特定文件編碼,而讀取時,反之。
二進制I/O不需要轉換,所以二進制I/O比文本I/O更有效。如果向文件寫入字節,就是將原始的字節復制到文件中。當從文件讀取字節時,就會返回文件中的確切字節。
二進制文件與主機的編碼方案無關,因此是可移植的。任何機器上的Java程序都可以讀取Java程序所創建的二進制文件。
Java類文件存儲為二進制文件,可以在任何具有Java虛擬機的機器上運行。
47.什么是內部類?什么是匿名內部類?
內部類(Inner class),或者稱為嵌套類,是一個定義在另外一個類范圍中的類。內部類對於定義處理器類特別有效。
public class line { Point p1,p2; class Point{//內部類 int x,y; Point(int x,int y) { this.x=x; this.y=y; } }; }
內部類可以使得程序 更加精簡。
內部類支持包含它的類的工作,可被編譯成一個名為OuterClassName$InnerClassName的類。
例如:Test類的內部類A,被編譯成Test$A.class。
一個匿名內部類是一個沒有名字的內部類。它將定義一個內部類以及創建一個內部類的實例結合在一步實現。
匿名類不具有類名,不具有抽象性,不能派生出子類。通常用在圖形用戶界面(GUI)設計中進行各種事件處理,如鼠標事件、按鈕事件和鍵盤事件等。
48.什么是UTF-8?為什么使用UTF-8?
UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,又稱萬國碼。
由於許多應用程序只需要ASCII碼字符集,所以將8位ASCII表示為16位的Unicode碼是很浪費的,為解決這個問題出現了一些中間格式字符集,它允許系統可以同時操作Unicode碼及ASCII碼,UTF-8就是其中一種。
49.什么可序列化的(serializable)對象?一個對象如何實現可序列化。
並不是每一個對象都可以寫到輸出流。可以寫入輸出流中的對象稱為可序列化的。
可序列化的對象的類必須實現Serializable接口。Serializable接口是一種標記性接口。因為它沒有方法,所以,不需要在類中為實現Serializable接口增加額外的代碼。
實現這個接口,可啟動Java序列化機制,自動完成存儲對象和數組的過程。
50.JVM(java虛擬機)中有幾個比較重要的內存區域:方法區、常量池、堆區、棧區,這幾個區域在java類的生命周期中扮演着比較重要的角色,他們的作用分別是什么?
堆:存放所有new出來的對象實例
棧:存放基本類型的變量數據和對象的引用,但對象本身不存放在棧中,而是存放在堆(new 出來的對象)
常量池:存放字符串常量(string)和基本類型常量(public static final)
方法區:用於存儲虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼數據。
分析程序寫結果
1、
import java.io.*; public class Test{ public static void main(String args [ ]){ AB s = new AB("Hello!","I love JAVA."); System.out.println(s.toString( )); } } class AB { String s1; String s2; public AB(String str1, String str2) { s1 = str1; s2 = str2; } public String toString( ){ return s1+s2; } }
Hello!I love JAVA.
2、
class Animal { Animal() { System.out.print("Animal"); } } public class Test extends Animal { Test() { System.out.print("Dog "); } public static void main(String[] args) { Test snoppy = new Test(); } }
AnimalDog
3、
public class Father { String name, address, tel; int age; public Father(String name, int age) { this.name = name; this.age = age; } void out() { System.out.print("姓名:" + name); System.out.print(" 年齡:" + age); } void outOther() { System.out.print(" 家庭住址:" + address); System.out.print(" 電話:" + tel); } }
class Son extends Father { String school; public Son(String name, int age) { super(name, age); } void out() { super.out(); super.outOther(); System.out.println("學校:" + school); } public static void main(String args[]) { Son son = new Son("Tom", 15); son.address = "金水區"; son.school = "九中"; son.tel = "66123456"; son.out(); } }
姓名:Tom 年齡:15 家庭住址:金水區 電話:66123456學校:九中
4、
abstract class Shape { abstract void display(); } class Circle extends Shape { void display() { System.out.println("Circle"); } } class Rectangle extends Shape { void display() { System.out.println("Rectangle"); } } class Triangle extends Shape { void display() { System.out.println("Triangle"); } } public class AbstractClassDemo { public static void main(String args[]) { Shape p; p = null; int which; for (which = 0; which < 3; which++) { switch (which) { case 0: p = new Circle(); break; case 1: p = new Rectangle(); break; case 2: p = new Triangle(); break; } p.display(); } return; } }
Circle
Rectangle
Triangle
5、
public class Father{ int a=100; public void miner(){ a--; } public static void main(String[] args){ Father x = new Father(); Son y = new Son(); System.out.println(y.a); System.out.println( y.getA()); y.miner(); System.out.println(y.a); System.out.println(y.getA()); } } class Son extends Father{ int a = 0; public void plus(){ a++; } public int getA() { return super.a; } }
0 100 0 99
要注意這里的基礎關系,子類本身就有一個變量a了,但父類也有一個a,這樣子類就有兩個a變量
6、
public class StringExample { String str = new String("good"); char[] cArray = { 'a', 'b', 'c' }; public static void main(String args[]) { StringExample se = new StringExample (); se.change(se.str, se. cArray); System.out.println(se.str + " and " ); System.out.print(se.cArray); } public void change(String str, char ch[]) { str = "test ok"; ch[0] = 'g'; } }
good and
gbc
change函數中傳遞的都是引用,但String是不可變類, str = "test ok"創建了一個新的字符串常量。
7、
public class StringTest{ public static void main(String args[]) { String str1 = "Application"; String str2 = new String("Application"); String str3 = "Application"; if (str1 == str2){ System.out.println("str1 == str2 is true"); } if (str1 == str3){ System.out.println("str1 == str3 is " + (str1 == str3)); } } }
str1 == str3 is true
注意這里str1和str2是存放在常量池中的,它們有着相同的引用地址
而str3是new出來的,雖然常量池中已經有"Application"了,但還會在內存(不是字符串常量池中,而是在堆里面)上創建一個新的String對象,二者的引用不同。
編程題
1.采用面向對象的方式編寫一個通迅錄管理程序,通迅錄中的信息包括:姓名,公司,聯系電話,郵編。要求的操作有:添加一個聯系人,列表顯示所有聯系人。先給出類定義,然后給出類實現。(提示:可以設計二個類,一個通迅錄條目類CommEntry,一個通訊錄類Commus)
CommEntry.java
public class CommEntry { private String name; private String company; private String tels; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public String getTels() { return tels; } public void setTels(String tels) { this.tels = tels; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "CommEntry [name=" + name + ", company=" + company + ", tels=" + tels + ", address=" + address + "]"; } }
Commus.java
import java.util.ArrayList; import java.util.Scanner; public class Commus { private ArrayList<CommEntry> ace = new ArrayList<CommEntry>(); public void add() { CommEntry ce = new CommEntry(); Scanner input = new Scanner(System.in); String name= input.nextLine(); String company= input.nextLine(); String tels= input.nextLine(); String address= input.nextLine(); ce.setName(name); ce.setCompany(company); ce.setTels(tels); ce.setAddress(address); ace.add(ce); }; public void display() { for(int i=0;i<ace.size();i++) { System.out.println(ace.get(i).toString()); } } public static void main(String []args) { Commus c = new Commus(); c.add(); c.add(); c.display(); } }
2.設計實現一個類模擬整數棧操作。
import java.util.ArrayList; public class MyStack { private ArrayList<Object> list = new ArrayList<>(); public boolean isEmpty() { return list.isEmpty(); } public int getSize() { return list.size(); } public Object peek() { return list.get(getSize() - 1); } public Object pop() { Object o = list.get(getSize() - 1); list.remove(getSize() - 1); return o; } public void push(Object o) { list.add(o); } @Override public String toString() { return "stack: " + list.toString(); } }
2. 定義一個表示學生信息的類Student,要求如下:
(1)類Student的成員變量:
sNO 表示學號;sName表示姓名;sGender表示性別;sAge表示年齡;sJava:表示Java課程成績。
(2)類Student帶參數的構造函數:
在構造函數中通過形參完成對成員變量的賦值操作。
(3)類Student的函數成員:getNo():獲得學號;getName():獲得姓名;getGender():獲得性別; getAge()獲得年齡;getJava():獲得Java 課程成績
(4)根據類Student的定義,創建五個該類的對象,輸出每個學生的信息,計算並輸出這五個學生Java語言成績的平均值,以及計算並輸出他們Java語言成績的最大值和最小值。
public class Student { private String sNo; private String sName; private String sGender; private String sAge; private String sJava; public Student(String sNo,String sName,String sGender,String sAge,String sJave) { this.sNo=sNo; this.sName= sName; this.sGender=sGender; this.sAge=sAge; this.sJava=sJave; } public Student() { } public String getsNo() { return sNo; } public String getsName() { return sName; } public String getsGender() { return sGender; } public String getsAge() { return sAge; } public String getsJava() { return sJava; } @Override public String toString() { return "Student [sNo=" + sNo + ", sName=" + sName + ", sGender=" + sGender + ", sAge=" + sAge + ", sJava=" + sJava + "]"; } }
import java.util.Scanner; public class StudentDom { public static void main() { Student[] st = new Student[3]; System.out.println("請錄入學生學號、姓名、性別、年齡、成績:"); Scanner in = new Scanner(System.in); for (int i = 0; i < st.length; i++) { st[i] = new Student(in.nextLine(), in.nextLine(), in.nextLine(), in.nextLine(), in.nextDouble()); } Student s1=null;//創建一個為空的對象進行數據交換 for(int i=0;i<st.length;i++) { for (int j =0; j < st.length; j++) { if(j!=4)//這里必須加上這個條件,不然數字會報出越界的問題 if(st[j].getsJava()<st[j+1].getsJava()) { s1=st[j+1]; st[j+1]=st[j]; st[j]=s1; } } } System.out.println("學生的成績排名如下\n姓名\t學號\t成績"); for (int i = 0; i < st.length; i++) { System.out.println(st[i].toString()); } } }