2012-11-03 69 views
1

我在爲我的入門編程課程做家庭作業。我們最近了解了構造函數,以及它們如何工作以及它們如何工作,但我不明白爲什麼每個對象都需要它。這似乎只是額外的工作,因爲你可以實例化對象並在它們之外運行語句。例如,在測試不同的方式來寫相同的代碼後,我發現,構造函數是必需的還是僅用於方便?

public class MyCartoon extends Frame { 
    StickFigure man = new StickFigure(); 
    public static void main(String[] args) {  
     new MyCartoon(); 
    } 
} 

產生正是因爲這個同樣的效果:

public class MyCartoon extends Frame { 
    StickFigure man; 
    public MyCartoon() { 
     man = new StickFigure(); 
    } 
    public static void main(String[] args) { 
     new MyCartoon(); 
    } 
} 

我可以請得到一些澄清?

但是,當我嘗試使用上面代碼實例化的另一個類中的類似代碼時,它在嘗試編譯時會拋出100多個錯誤。以下代碼運行良好。同樣的代碼,除了與StickFigure()構造函數中的代碼,不會:

import wheels.users.*; 
import java.awt.Color; 

public class StickFigure { 

Ellipse head; 
Line torso; 
Line leftBackArm; 
Line leftForeArm; 
Line rightBackArm; 
Line rightForeArm; 
Line leftUpperLeg; 
Line leftLowerLeg; 
Line rightUpperLeg; 
Line rightLowerLeg; 

StickFigure() { 

    head = new Ellipse(); 
    head.setColor(Color.WHITE); 
    head.setFrameThickness(4); 
    head.setFrameColor(Color.BLACK); 
    head.setSize(80, 80); 
    head.setLocation(140, 130); 

    torso = new Line(180, 210, 160, 340); 
    torso.setColor(Color.BLACK); 
    torso.setThickness(4); 

    leftBackArm = new Line(180, 210, 145, 280); 
    leftBackArm.setColor(Color.BLACK); 
    leftBackArm.setThickness(4); 

    leftForeArm = new Line(145, 280, 132, 340); 
    leftForeArm.setColor(Color.BLACK); 
    leftForeArm.setThickness(4); 

    rightBackArm = new Line(180, 210, 190, 290); 
    rightBackArm.setColor(Color.BLACK); 
    rightBackArm.setThickness(4); 

    rightForeArm = new Line(190, 290, 225, 350); 
    rightForeArm.setColor(Color.BLACK); 
    rightForeArm.setThickness(4); 

    leftUpperLeg = new Line(160, 340, 140, 420); 
    leftUpperLeg.setColor(Color.BLACK); 
    leftUpperLeg.setThickness(4); 

    leftLowerLeg = new Line(140, 420, 105, 490); 
    leftLowerLeg.setColor(Color.BLACK); 
    leftLowerLeg.setThickness(4); 

    rightUpperLeg = new Line(160, 340, 180, 420); 
    rightUpperLeg.setColor(Color.BLACK); 
    rightUpperLeg.setThickness(4); 

    rightLowerLeg = new Line(180, 420, 180, 500); 
    rightLowerLeg.setColor(Color.BLACK); 
    rightLowerLeg.setThickness(4); 

    } 
} 

爲什麼會變成這樣的代碼,而不是第一個代碼塊,拋出錯誤沒有提供的構造?

回答

10

你出什麼(使用compiler-provided default constructor和變量初始化的)是好的,如果:

  • 你的初始化永遠不需要拋出任何checked異常
  • 你只需要內賦值給變量初始化,而不是做什麼其他。 (你可以寫更復雜的代碼初始化塊,但如果你打算這樣做,你還不如讓一個構造函數。)
  • 你不需要任何參數的構造函數

在我的經驗,這些都是相對很少都是真實的,特別是最後一點。當然如果你以後很樂意設置屬性,你可以不用管理 - 但我個人喜歡不可變的類型,它幾乎總是需要構造函數參數

那麼,考慮一下你要如何寫這個類沒有構造函數,但保留其所有其他功能:

public class Person { 
    private final String name; 
    private final LocalDate dateOfBirth; 

    public Person(String name, LocalDate dateOfBirth) { 
     this.name = name; 
     this.dateOfBirth = dateOfBirth; 
    } 

    public String getName() { 
     return name; 
    } 

    public LocalDate getDateOfBirth() { 
     return dateOfBirth; 
    } 
} 
+0

謝謝!這解釋了很多。然而,你的第一個子彈給我帶來了一些困惑。我寫了一些更多的代碼,並且在等待答案時也嘗試了包含的構造函數/無構造函數測試。新代碼不需要拋出任何異常或任何其他項目符號,但是如果我拿出表示構造函數的語法,它就會失敗。我將在短時間內編輯代碼。 – Eunkai

+0

@refusetocompile:是的,我的例子不包括任何異常 - 但看看'FileInputStream'就是一個例子。 –

+0

您能否根據我編輯的新代碼進行說明?爲什麼這段代碼除了構造函數內部的所有語句外,都會拋出這麼多的錯誤? – Eunkai

4

它不是你的第一個代碼不使用構造函數。它的確如此。不同之處在於,它使用了編譯器提供的默認構造函數,如果您不提供任何編譯器,編譯器會提供該構造函數。

構造函數用於初始化新創建的對象的狀態。要麼你明確地給你的構造函數,要麼編譯器自己添加一個默認的構造函數。

其實,your first code after compilation變成這樣: -

StickFigure man; 
public MyCartoon() { 
    super(); 
    man = new StickFigure(); 
} 
public static void main(String[] args) {  
    new MyCartoon(); 
} 

所以,你可以看到,有幾乎在所有的第1和第2的代碼之間沒有區別。 (注意: - 編譯器增加了一個super調用作爲第一條語句,你有充分的構造函數,如果你沒有自己的superthis呼叫執行)

在上面的代碼中會發生什麼事是 - 編譯器增加了一個默認的構造函數,然後在構造函數中移動您在位置完成的所有實例變量初始化。 如果您已經給出了多個構造函數(在這種情況下,編譯器將不提供默認的構造函數),那麼編譯器會將instance variable初始化代碼移動到每個構造函數中。

+0

+1尼斯的答案! –

+0

很好的解釋。簡短而準確。謝謝! – Eunkai

+0

@refusetocompile。歡迎您:) –

相關問題