10

I know that private instance variables are accessed through their public getters and setters method.

But when I generate constructors with the help of IDE, it initializes instance variables directly instead of initializing them through their setter methods.

Q1. So should I change the IDE generated code for constructors to initialize those instance variables through their setter methods.

Q2. If yes, then why IDE don't generate constructors code in that way?

============================= EDITED =======================================

  • I use Eclipse and Netbeans IDE

  • It's a general question. But as asked by @Lords would the answer depends on whether our constructor is public or protected or package private or private?

4

7 に答える 7

12

コンストラクターから非最終メソッドを呼び出してはなりません。クラス コンストラクターを使用してオブジェクトを初期化します。コンストラクターが戻るまで、オブジェクトは一貫した状態になりません。コンストラクターが、後でサブクラスによってオーバーライドされる非最終メソッドを呼び出すと、オーバーライドされたメソッドが呼び出されたときにオブジェクトが完全に初期化されていないため、奇妙で予期しない結果が生じる可能性があります。

この不自然な例を考えてみましょう:

class A {
    private int x;

    public A() {
        setX(2);
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return x;
    }
}

class B extends A {
    private int number = 10;

    @Override        
    public void setX(int x) {
        // set x to the value of number: 10
        super.setX(number);
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // b.getX() should be 10, right?
        System.out.println("B.getX() = " + b.getX());
    }
}

このプログラムの出力は次のとおりです。

B.getX() = 0

その理由は、Bnumberメンバーが呼び出された時点で初期化されていないsetXため、デフォルト値の0が使用されるためです。

この記事には、 Effective Javaと同様に、より詳細な説明があります。

于 2010-04-02T20:23:55.667 に答える
2

コンストラクターは初期化用です。コンストラクターでプライベート インスタンス変数を直接初期化します。メソッドは、オブジェクトの動作を定義します。インスタンス化/初期化後に動作が発生します。セッター メソッドでインスタンス変数の状態を操作します。これは古典的な OOP の考え方であり、おそらく IDE がコードを生成する理由です。

于 2010-04-02T19:21:07.810 に答える
1

場合によります。セッター/ゲッターが単にメンバーにアクセスしている場合は、それらに直接アクセスする必要があります。それに付随するコードもある場合は、セッターを使用してください。

于 2010-04-02T18:55:37.733 に答える
0

クラスのプライベート インスタンス変数は、クラス コンストラクターの外で宣言する必要があります (そうする必要があると思います)。あなたの質問の一部を2つの部分に分けることができれば:

Q1) ローカル変数とは異なり、クラスのインスタンス化時にインスタンス変数が初期化される場合、特定のクラス コンストラクター内でわざわざ余分な作業を行うのはなぜですか (?)。

A1) インスタンス変数を初期化する必要はありませんが (プライベート文字列 someString; デフォルトは null で有効です)、そうする理由の 1 つは、コンパイラによって割り当てられたデフォルト値が必要な値ではないか、さらに悪いことに、正しくない可能性があるためです (コンパイラがキャッチする必要があります)。

Q2) 上記の部分を前提として、get の意味は何ですか。設定; プロパティ?

A2) メソッドと同等のものよりも簡単でエレガントであるという事実は別として、プロパティはクラス内でいつでも使用でき (明らかに)、単純な割り当てとして使用したり、追加のコードを含めることができます (情報を検証するために誰かが既にこれを述べています)。 、そして最後に、データはクラス内に自己完結しているため、デバッグが容易になります。

以上のことから、本や他の人が言っていることとは異なることをする完全に正当な理由があるかもしれません。「ルール」には常に受け入れがあり、それに応じてコーディングする必要があります。

于 2010-08-05T18:40:59.743 に答える
0

良い答え。Eclipse (私が頻繁に使用するもの) にはテンプレートがあり、それを変更して、必要な方法でコードを生成できることを追加したいだけです。必要に応じてコードを調整すると役立つ場合があります。

PS。私はむしろセッターとゲッターを使用します。習慣がコードの一貫性を維持するのと同じように、コード全体に習慣を維持すると、他の人にとって読みやすくなると思います。

于 2010-04-02T19:24:17.393 に答える
0

コンストラクターで初期化するフィールドとセッターで初期化するフィールドを決定する必要があります。(両方とも可能です) 私は可能な限りコンストラクターのみを使用することを好み、多くの場合、セッターはありません。

これは、IDE で設定/選択できる必要があります。IDE を知らなければ、なぜそのように動作するのかを知る方法はありません。

于 2010-04-02T18:56:24.943 に答える
0

まず第一にinitialization != setters(少なくとも常にではありません)

しかし、IDE は、かつて崇拝されていた JavaBean デザイン パターンをうまく利用しているだけです。

だから、それはデザインの問題です。クラスが純粋な値オブジェクトを表している場合は、初期化を行っても害はありません= 。しかし、クラスのJavaBeanプロパティの変更が単なる初期化や代入以上のものになる可能性がある場合は、set*呼び出しを使用してください。

于 2010-04-02T19:29:54.837 に答える