<address id="ousso"></address>
<form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
  1. java語言

    Think in Java之構造器的真正調用順

    時間:2025-03-19 04:59:28 java語言 我要投稿
    • 相關推薦

    Think in Java之構造器的真正調用順

      構造器是OOP的重要組成部分,很多人認為它很容易。只不過是new了一個對象而已。而think in java的作者卻告訴我們,其實這并不容易。下面一起學習一下吧!

      先看下面這個例子。在你沒看結果之前,你覺得你的答案是對的么。

      package com.tudou.t1;

      class Meal {

      Meal() {

      System.out.println("meal");

      }

      }

      class Bread {

      Bread() {

      System.out.println("Bread");

      }

      }

      class Cheese {

      Cheese() {

      System.out.println("Cheese");

      }

      }

      class Lettuce {

      Lettuce() {

      System.out.println("Lettuce");

      }

      }

      class Lunch extends Meal{

      Lunch() {

      System.out.println("Lunch");

      }

      }

      class PortableLunch extends Lunch{

      PortableLunch() {

      System.out.println("PortableLunch");

      }

      }

      public class Sandwich extends PortableLunch {

      private Bread b = new Bread();

      private Cheese c = new Cheese();

      private Lettuce l = new Lettuce();

      public Sandwich() {

      System.out.println("Sandwich");

      }

      public static void main(String[] args) {

      new Sandwich();

      }

      }

      控制臺的打印結果為:

      meal

      Lunch

      PortableLunch

      Bread

      Cheese

      Lettuce

      Sandwich

      復雜對象調用構造器的順序應該遵循下面的原則:

      1、調用基類[即父類]構造器。這個步驟會不斷反復遞歸下去,首先是構造器這種層次結構的根,然后是下一層導出類[即子類],等等。直到最底層的導出類。[從最上層的meal一直遞歸到PortableLunch]

      2、按聲明順序調用成員的初始化方法。[即上面的Bread,Cheese,Lettuce]

      3、調用導出類構造器的主體[即Sandwich]

      可見,調用類本身是最后完成初始化的,最先完成初始化的是最頂級的基類,所謂沒有父親,哪來的兒子。處于它們中間的是調用類本身擁有的子對象。因為你不可能在子對象初始化之前用本類調用它,所以它一定在本類調用之前,父類調用之后完成初始化的。

      那么這個說法是不是一定成立呢。結果是否定的。你必須知道JVM的編繹原理才可能知道,它究竟是如何工作的。

      我們來看下面這個例子,來解釋為什么它不一定。因為在繼承和重寫的時候,這種情況變得有點詭異。

      深入探究:

      package com.tudou.t1;

      public class ConstrcutorTest2 {

      public static void main(String[] args) {

      new RoundGlyph(5);

      }

      }

      class Glyph {

      void draw() {

      System.out.println("Glyph draw()");

      }

      Glyph() {

      System.out.println("Glyph before draw();");

      draw();

      System.out.println("Glyph after draw();");

      }

      }

      class RoundGlyph extends Glyph {

      private int radius = 1;

      RoundGlyph(int r) {

      radius = r;

      System.out.println("RoundGlyph(),radius:" + radius);

      }

      void draw() {

      System.out.println("RoundGlyph.draw(),radius:" + radius);//此處打印是0,而不是1

      }

      }

      控制臺打印結果:

      Glyph before draw();

      RoundGlyph.draw(),radius:0

      Glyph after draw();

      RoundGlyph(),radius:5

      為什么RoundGlyph.draw(),radius:0這里會是0呢。

      默認的1哪去了?值自己會變么。其實上面的講述并不完整。,而這正是解決謎題的關鍵所在。初始化的實際過程之前,實際在還有一步。

      0:在其他任何事物發生之前,將分配對象的存舍得空間初始化為二進制的零。

      而它后面的初始化順序就是上面的3步。

      調用基類[即父類]構造器。這個步驟會不斷反復遞歸下去,首先是構造器這種層次結構的根,然后是下一層導出類[即子類],等等。直到最底層的導出類。

      按聲明順序調用成員的初始化方法。

      調用導出類構造器的主體

      也就是說,實際上有4步,知道這些你對對象初始化構造器才可能有個清楚的認識。

      JAVA有更多的精髓等著人們去挖掘,而不僅僅是知道如何去使用它。

      因為你不知道什么時候它會出現意想不到的后果,而這個錯誤,可能你根本就想不出來。

      編寫構造器時有一條準則:

      用盡可能簡單的方法使對象進入正常狀態,如果可以的話,避免調用其它方法。

      在構造器內唯一能夠安全調用的那些方法是基類中的final或者private方法,這些方法不能被覆蓋,因此也就不會出現令人驚訝的問題。

      你可能無法總是遵循這條準則,但是應該朝著它努力。

      學任何語言,請打好基礎,它是你以后擴展的人生基石。

    【Think in Java之構造器的真正調用順】相關文章:

    java構造函數調用技巧10-26

    java調用的方法09-04

    Java調用瀏覽器打開網頁完整實例11-14

    java調用的幾個方法07-27

    Java調用瀏覽器打開網頁實例完整版11-06

    java調用c函數的實例09-16

    java如何構造09-21

    在Java中調用存儲的過程10-04

    Java遠程方法調用RMI08-24

    <address id="ousso"></address>
    <form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
    1. 日日做夜狠狠爱欧美黑人