これまでに、Javaで変数の値を設定する2つのアプローチを見てきました。引数を持つコンストラクターが使用される場合もあれば、各変数の値を設定するために他のセッターメソッドが使用される場合もあります。
クラスが「新しい」キーワードを使用してインスタンス化されると、コンストラクターがクラス内のインスタンス変数を初期化することを知っています。
しかし、いつコンストラクターを使用し、いつセッターを使用するのでしょうか?
すでに値が設定されたオブジェクトの新しいインスタンスを作成する場合は、コンストラクターアプローチを使用する必要があります(値が設定されたオブジェクトをすぐに使用できます)。この方法では、オブジェクト内の各フィールドのセッターメソッドを明示的に呼び出してそれらを設定する必要はありません。
オブジェクトの作成後にフィールドの値を変更する場合は、セッターアプローチを使用して値を設定します。
例:-
MyObject obj1 = new MyObject("setSomeStringInMyObject"); // Constructor approach
// Yippy, I can just use my obj1, as the values are already populated
// But even after this I can change the value
obj1.setSomeString("IWantANewValue"); // Value changed using setter, if required.
..
MyObject obj2 = new MyObject();
obj2.setSomeString("setSomeStringNow"); // Setter approach
// values weren't populated - I had to do that. Sad :(
Axelが述べたように、不変オブジェクトを作成したい場合、setter-methodsアプローチを使用できません。不変オブジェクトでも使用できる遅延評価など、さまざまなアプローチが存在するため、コンストラクターですべてを初期化する必要があるとは言いません。
あなたは良い質問をしたと思います:-しかし、いつコンストラクターを使用し、セッターを使用するのですか?
まず、いくつかの概念から始めましょう。この説明が、コンストラクターまたはsetters()メソッドとgetters()メソッド(アクセサーとミューテーター)をいつ使用するかを知りたいすべての人に役立つことを願っています。 ConstructorsはMethodsと似ていますが、constructorにはほとんど違いがありません=およびmethodJavaの場合:
1)Constructorは、オブジェクトの状態を初期化するために使用されます。 Methodは、オブジェクトの動作を公開するために使用されます。
2)Constructorには戻り型を含めることはできません。 Methodには戻り型が必要です。
3)Constructorは暗黙的に呼び出されます。 Methodは明示的に呼び出されます。
4)Getters()、またはアクセサは、オブジェクトのインスタンス変数へのアクセスを提供するメソッドです。 Setters()、またはミューテーターは、特定のインスタンス変数の値を更新する機会を呼び出し元に提供するメソッドです。
これを明確にして、オブジェクト指向プログラミング(OOP)の観点から、OOPプリンシパル(オブジェクト指向プログラミング(OOP)は4つの主要な原則:カプセル化、データ抽象化、多態性および継承。)、- Getter()およびSetter()メソッドは、これを達成するための鍵です。
ここに私が何を意味するかを示す公式があります:
プライベートフィールド+パブリックアクセサー==カプセル化。
この式に基づいてプライベートフィールドを設定し、パブリックアクセサーを使用すると、4 OOPプリンシパルの1つをカプセル化することがわかります。
ここで、2つのクラスを提供します。コードに自己説明をさせようと、コメントを追加しました。これらのクラスをCustomer
およびTestCustomer
[main()
method]クラスのあるメソッドのラボと見なして、コードをコピーして自分で実行できます。注:複数のコンストラクターを持ち、プライベートインスタンス変数にアクセスするためにpublic setters()
メソッドとgetters()
メソッドを持つクラスを説明するために、2つのコンストラクターを使用しました。
_package com.exercise.lecture2;
/**
* 1) Create a Customer class that has the following attributes:
* name, SSN.
* 2) This class should have two methods: getName() and getSSN().
* 3) If the class is instantiated with only a SSN, then give the default name of "John Doe". (HINT: Use two constructors)
* 4) Also, add a method toString(), that returns a string representation of the customer object (name and SSN concatenated).
* Make sure to set this method public.
* 5) Create a class to test your program (e.g. a class that include the main() method). In your test program, instantiate
* three customers and print out the value using toString() method.
*
* @author Samuel M.
*
*/
//this class is complemented with class TestLabCustomer.Java
public class LabCustomer {
// Private filds: name and socialSecurityNum
private String name;
private int socialSecurityNum;
// constructors
public LabCustomer(String name, int socialSecurityNum) {
this.name = name;
this.socialSecurityNum = socialSecurityNum;
}
/** The keyword 'this' can be used to call a constructor from a constructor,
* when writing several constructor for a class, there are times when
* you'd like to call one constructor from another to avoid duplicate code.
*/
// Account with This() on a second constructor
public LabCustomer(int socialSecurityNum) {
this("John Doe", socialSecurityNum); // default name is printed if only the SSN is provided
}
// Public accessors (getters and setters)
String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
int getSSN() {
return socialSecurityNum;
}
void setSSN(int socialSecurityNum) {
this.socialSecurityNum = socialSecurityNum;
}
// instance method
public String toString() { //overriding the toString() method
return ("Customer name: " + getName() + ", SSN#: " + getSSN() ); // concatenating the name and SSN
}
}
_
テストクラスは、main()
メソッドを持ち、プレビュークラスのオブジェクトをインスタンス化した後にインスタンスメソッドを呼び出します。
_package com.exercise.lecture2;
//this class is complemented with class LabCustomer.Java
public class TestLabCustomer {
public static void main(String[] args) {
// Instantiating an object of class LabCustomer and creating three customers objects
LabCustomer cust1 = new LabCustomer("Juan Melendez", 123457789);
LabCustomer cust2 = new LabCustomer("Mary Lee", 125997536);
LabCustomer cust3 = new LabCustomer(124963574); // when instantiating with no "name", the default (John Doe) is printed
/**
* Once you've instantiated an object and have an object variable,
* you can use object variable to call an instance method.
* e.g.:
* object variables: cust1, cust2, cust3
* call the method toString() using the object variable and dot [.] in order to perform the method call.
*/
// calling method toString() in class LabCustomer to print customer values
System.out.println(cust1.toString());
System.out.println(cust2.toString());
System.out.println(cust3.toString());
}
}
_
結果:
お客様名:Juan Melendez、SSN番号:123457789
お客様名:メアリーリー、SSN番号:125997536
お客様名:John Doe、SSN#:124963574
不変クラスを作成する場合はコンストラクターを使用し、そうでない場合はセッターを使用します。
簡単な言葉で:
オブジェクトを使用する前に初期化が必須と思われる場合は、constructorを使用します。
変数の初期化がオブジェクトを使用するために必須ではない場合、setterメソッドを使用します。
詳細については、ドキュメント page を参照してください。
Counterという名前のクラスがあるとします:
public class Counter{
int count;
//constructor
public Counter(int c){
count = c;
}
public void setCounter(int newCounter){
count = newCounter;
}
}
上記のクラスで、new Counterオブジェクトを作成する場合は、コンストラクターを使用して、その中にcount変数を設定します。そのようです:
Counter myCounter = new Counter(1);
カウント変数実行時を変更する場合は、setterメソッドを使用します。
myCounter.setCounter(2);
シナリオに応じてアプローチを使用します。
クラスのオブジェクトをインスタンス化するときに値のセットがある場合、その時点でコンストラクターアプローチを使用します。
その時点でオブジェクトのインスタンスを作成しているときに値のセットがわからない場合は、セッターアプローチを使用します。
それは、アプリケーションドメインとその中のクラスの目的に依存します。
Java Beanには通常、引数なしのコンストラクターと、関連するメンバー変数のゲッター/セッターがあります。 Java BeanはStrutsやSpringなどの多くのフレームワークですぐにサポートされているため、このアプローチには利点があります。
クラスは、このような変数をパラメーターとして基本コンストラクターに渡すことにより、値の必須の可用性を強制することもできます。また、必須ではない値は、他の便利なコンストラクターまたはセッターメソッドを介して設定できます。
一方、不変クラスにはコンストラクターを含めることができますが、セッターなどの状態を変更する不在メソッドが必要です。
全体として、このような決定は、アプリケーション、フレームワークの全体的な設計を考慮して行うことができます1 実行、強制しなければならない契約など。
1-ただし、クラス設計はフレームワークに依存しないことが推奨されます。Springのような優れたフレームワークは、そのような要件を強制しません。
コンストラクタの場合、フィールドを更新するときに、newキーワードを使用して毎回新しいオブジェクトを作成します。
Customer customer = new Customer("Tom", 23, 10000);
たとえば、Tomの給与を更新する場合、更新された給与でこの行を再度記述する必要があります。つまり、メモリが無駄になります。
セッターメソッドの場合、元のオブジェクトにのみ個々のフィールドを設定できます。
ほとんどの場合、私はそれらの両方を使用します:)(9/10回戻って何かを編集したいので(そしてそれはそれの新しいインスタンスを作成するのに良い実用的ではありません)
私は通常、次のようなものを作ります
public class User {
private int id;
private String initials;
private String firstName;
private String lastName;
private String email;
public User() {
this(0, "", "", "");
}
public User(int id, String firstName, String lastName, String email) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// Getters and setters should be here
}
そして、それを使って何かを編集したい場合は、セッターを使用するだけです(たとえば、ユーザーをArrayListに保存する場合、配列リストからオブジェクトを取得し、編集したいフィールドを設定するだけでよいのです) 、それの真新しいオブジェクトを作成する代わりに:)
2つのアプローチを組み合わせることができます。コンストラクター内で、インスタンス変数のセッターを呼び出すことができます。何かのようなもの:
public class TestClass {
private String someField;
public TestClass(String someField) {
setSomeField(someField);
}
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
}