たとえば、ユーティリティメソッドでクラスを作成したい
public class Util {
public static void f (int i) {...}
public static int g (int i, int j) {...}
}
ユーティリティクラスを作成する最良の方法はどれですか?
プライベートコンストラクターを使用する必要がありますか?
抽象クラスのユーティリティクラスを作成する必要がありますか?
何もするべきではありませんか?
Javaの完全にステートレスなユーティリティクラスの場合、public
およびfinal
としてクラスを宣言し、インスタンス化を防ぐためのプライベートコンストラクターを用意することをお勧めします。 final
キーワードはサブクラス化を防ぎ、実行時の効率を改善できます。
クラスにはすべてのstatic
メソッドを含める必要があり、abstract
として宣言しないでください(クラスが具体的ではなく、何らかの方法で実装する必要があることを意味します)。
クラスには、提供されたユーティリティのセットに対応する名前を付ける必要があります(クラスが幅広い未分類のユーティリティを提供する場合は「Util」)。
ネストされたクラスがユーティリティクラスでもある場合を除き、クラスにネストされたクラスを含めることはできません(ただし、この方法は複雑で読みにくくなります)。
クラスのメソッドには適切な名前を付ける必要があります。
クラス自体によってのみ使用されるメソッドはプライベートである必要があります。
クラスには、非最終/非静的クラスフィールドを含めることはできません。
このクラスは、コードの可読性を向上させるために他のクラスによって静的にインポートすることもできます(ただし、これはプロジェクトの複雑さに依存します)。
例:
public final class ExampleUtilities {
// Example Utility method
public static int foo(int i, int j) {
int val;
//Do stuff
return val;
}
// Example Utility method overloaded
public static float foo(float i, float j) {
float val;
//Do stuff
return val;
}
// Example Utility method calling private method
public static long bar(int p) {
return hid(p) * hid(p);
}
// Example private method
private static long hid(int i) {
return i * 2 + 1;
}
}
おそらく最も重要なことは、各メソッドのドキュメントが正確で記述的であることです。このクラスのメソッドは非常に頻繁に使用され、コードを補完するために高品質のドキュメントを作成するのに適しています。
Joshua Bloch(Effective Java)によると、常に例外をスローするプライベートコンストラクターを使用する必要があります。最終的には、ユーザーがutilクラスのインスタンスを作成することを思いとどまらせます。
abstractはクラスが継承用に設計されていることを読者に示唆しているため、クラス抽象にマークを付けることはお勧めしません。
クラスをfinal
にし、すべてのメソッドをstatic
にします。
したがって、クラスを拡張することはできず、メソッドはClassname.methodName
によって呼び出すことができます。メンバーを追加する場合、それらが機能することを確認してくださいthread safe;)
クラスabstract
を作成すると、abstract
クラスのユーザーにサブクラスにしたいというメッセージをコードのリーダーに送信します。しかし、これはあなたがしたいことではありません:ユーティリティクラスはサブクラス化されるべきではありません。
したがって、ここではプライベートコンストラクターを追加することをお勧めします。また、クラスfinal
を作成して、ユーティリティクラスのサブクラス化を禁止する必要があります。