大家好!今天我繼續回顧 Java 開發者面試問題。
29. return 可以在建構函式中使用嗎?
是的,但只有return關鍵字右邊沒有值。您可以使用返回;作為建構函式中的輔助語句,用於緊急終止(中斷)進一步程式碼的執行並完成物件的初始化。例如,假設我們有一個Cat類,如果一隻Cat無家可歸(isHomeless = true,那麼我們想要終止初始化並且不填寫其他字段(畢竟,它們對我們來說是未知的,因為貓無家可歸歸) :public Cat(int age, String name, boolean isHomeless) {
if (isHomeless){
this.isHomeless = isHomeless;
return;
}
this.isHomeless = isHomeless;
this.age = age;
this.name = name;
}
但如果我們談論的是具體值,那麼return關鍵字就不能回傳特定值,因為:
- 當你聲明一個建構函數時,你不會有像返回類型這樣的東西;
- 通常,建構函數在實例化期間會隱式地呼叫;
- 建構子不是方法:它是一個單獨的機制,其唯一目的是初始化實例變量,也就是我們使用 new運算子來建立物件。
30. 建構函數可以拋出異常嗎?
構造函數處理異常的方式與方法相同。方法允許我們透過在方法頭中寫入throws <ExceptionType>來拋出異常。建構函數允許我們做同樣的事情。當我們繼承並定義子類別的建構子時,我們可以擴大異常類型 - 例如,IOException -> Exception(但反之則不然)。讓我們使用Cat類別的建構子作為建構子拋出異常的範例。假設當我們建立一個物件時,我們想要從控制台輸入名稱和年齡:public Cat() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
this.name = reader.readLine();
this.age = Integer.parseInt(reader.readLine());
}
由於reader.readLine()拋出 IOException,我們將其作為可能拋出的例外寫入標頭中。
31. 類別頭的元素是什麼?寫一個例子
為了說明構成類別頭的元素,讓我們來看一個小模式:- 強制元素出現在括號 <> 中
- 可選元素位於 {} 中
public final class Lion extends Cat implements WildAnimal
32. 方法頭的元素是什麼?寫一個例子
在考慮構成方法頭的元素時,讓我們再次考慮一個小模式:- 強制元素出現在括號 <> 中
- 可選元素位於 {} 中
public static void main(String[] args) throws IOException
33. 如果基底類別中尚未定義預設建構函數(但定義了不同的建構子),則在子類別中建立預設建構函數
我不確定我完全理解這個問題,但這也許意味著我們在父類別中有一些像這樣的建構子:public Cat(int age, String name) {
this.age = age;
this.name = name;
}
在這種情況下,在父類別中,我們肯定需要定義一個建構函式來初始化父類別(即呼叫父建構子):
public class Lion extends Cat {
public Lion(int age, String name) {
super(age, name);
}
}
34.什麼時候使用this關鍵字?
在 Java 中,這有兩種不同的意義。1. 它是對目前物件的引用,例如this.age = 9。也就是說,this指的是使用它的物件以及帶有this 的程式碼所指的物件。主要目的是提高程式碼可讀性並避免歧義。例如,如果實例欄位和方法參數具有相同的名稱:public void setName(String name) {
this.name = name;
}
也就是說,this.name是物件的字段,而name是方法參數。this引用不能在靜態方法中使用。2. 在建構子中,this可以像方法一樣被調用,例如this(value)。在這種情況下,它將呼叫同一類別的另一個建構函數。基本上,您可以在建立物件的過程中呼叫兩個建構函式:
public Cat(int age, String name) {
this(name);
this.age = age;
}
public Cat(String name) {
this.name = name;
}
當呼叫第一個建構函式建立Cat物件時,兩個實例欄位都會成功初始化。這裡有一些細微差別:
- this()僅適用於建構子。
- 對另一個建構函式的參考必須位於建構函式區塊(主體)的第一行。這意味著構造函數不能呼叫其類別的多個(其他)構造函數。
35.什麼是初始化器?
據我了解,這個問題是關於普通和靜態初始化塊的。讓我們先記住什麼是初始化。初始化是字段的創建、激活、準備和定義。準備程序或組件以供使用。你會記得,當你建立一個物件時,類別變數可以在宣告時立即初始化:class Cat {
private int age = 9;
private String name = "Tom";
或透過構造函數事後設定:
class Cat {
private int age;
private String name;
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
但還有另一種方法:您可以使用初始化區塊設定實例變量,該初始化區塊在類別中 採用大括號{} 的形式,沒有名稱(如無名方法或建構子):
class Cat {
private int age;
private String name;
{
age = 10;
name = "Tom";
}
初始化區塊是創建物件時載入的一段程式碼。此類區塊通常用於執行載入類別時所需的某些複雜計算。這些計算的結果可以設定為變數的值。除了普通的初始化塊之外,還有靜態的初始化塊。它們看起來相同,但在左大括號前面 有static關鍵字:
class Cat {
private static int age;
private static String name;
static{
age = 10;
name = "Tom";
}
此塊與前一個塊相同。但是,如果普通物件在初始化每個物件時執行,則靜態物件僅在類別載入時執行一次。通常,某些複雜的計算是在靜態區塊中執行的,用於初始化靜態類別變數。同樣的限制也適用於靜態方法的靜態區塊:不能使用非靜態數據,例如靜態區塊中 對目前物件 ( this ) 的引用。現在我們可以查看類別(及其父類別)的初始化順序,以便更好地理解何時調用初始化區塊。
36.給定一個擴展Parent的公共Child類,寫出該物件的初始化順序
當載入Child類別時,初始化順序如下:- 父類別的靜態類別欄位。
- 父類別的靜態初始化塊。
- Сchild類別的靜態欄位。
- Child類別的靜態初始化區塊。
- 父類別的非靜態欄位。
- 父類別的非靜態初始化塊。
- 父類別建構函數。
- Сhild類別的非靜態字段。
- Сhild類別的非靜態初始化塊。
- Сchild類別的建構子。
37.你知道類別(物件)之間有哪些關係?
Java 中有兩種變數:原始型別和對成熟物件的參考。- IS-A關係
Lion IS-A Cat
(但不是每隻貓都是獅子)介面也存在同樣的情況。如果Lion類別實作了WildAnimal接口,那麼它們也存在關係:
Lion IS-A WildAnimal
- HAS-A關係
Car HAS-A Passenger
反之亦然:如果Passenger引用了Car,那麼關係如下:
Passenger HAS-A Car
38.你知道哪些關聯對象關係?
聚合和組合只不過是關聯的特殊情況。 聚合是一種關係,其中一個物件是另一個物件的一部分。例如,乘客可能位於汽車內。更重要的是,可能有多名乘客,或者根本沒有乘客(如果我們談論的是特斯拉,可能沒有司機)。例如:public class Car {
private List passengers = new ArrayList<>();
void setPassenger(Passenger passenger) {
passengers.add(passenger);
}
void move() {
for (Passenger passenger : passengers) {
System.out.println("Transporting passenger - " + passenger.toString());
}
passengers.clear();
}
}
換句話說,乘客數量(任何數量)對我們來說並不重要:Car類的功能不依賴於此。聚合也意味著當另一個物件使用一個物件時,第一個物件可以被其他物件使用。例如,同一位學生可能同時參加針織俱樂部和搖滾樂隊,並同時參加西班牙語課程。正如你可以想像的,聚合是類別之間更鬆散的關聯關係。 組合是一種更緊密的關係,其中一個物件不僅是另一個物件的一部分,而且一個物件的工作非常依賴另一個物件。例如,汽車有引擎。引擎可以在沒有汽車的情況下存在,但離開汽車就毫無用處。沒有引擎汽車就無法運作:
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
void startMoving() {
engine.start();
...
}
組合也意味著當另一個物件使用一個物件時,第一個物件不能屬於任何其他物件。回到我們的例子,一台引擎只能屬於一輛汽車,不能同時屬於兩輛或更多汽車。我想今天的內容就夠了,所以我們就到此為止。
GO TO FULL VERSION