自問
Javaで複数の戻り値(タプル構造)を持つメソッドを定義する方法を教えてください。
ベストアンサー
Javaのメソッドは1つの「プリミティブデータ型」または「クラス」しか返すことができない。
そこで、複数の値を持つクラスを返す方法を考える。
Java1.6のAbstractMap.SimpleEntry<K, V>クラスを流用する方法がある。
JavaFX 2.0ではPair<K, V>クラスが追加された。
Android SDKであればandroid.util.Pair<F, S>クラスがある。
3つ以上の値を持つ標準クラスはない。
他に各種OSSライブラリが存在する。
しかし、私は、汎用クラスの使用はお勧めしない。
なぜならば、ネストしたジェネリクスによるアンチパターンと考えるから。
Pair<Pair<String, Integer>, Map<String, Pair<String, String>>> getHell(){
return hell;
}
そこで、以下に、メソッドデータ受け渡し専用のTupleクラスを提案する。
サンプルコード
/** タプル(メソッドデータ受け渡し用 構造体)、継承してデータアクセスの手段のみを定義すること。<br/> * <span style="font-size:1.2em;color:#FF8888;">hashCode、equals、clone、toStringへのアクセスはExceptionを生成する</span><br/> * <pre> * //内部クラスにするとthis参照を保持してしまうので注意。 * //再継承するのは本来の目的から離れるためfinal class推奨。 * //単純化するためメンバへの直接アクセス推奨。 * public static final class ExampleTuple extends AbsTuple { * public int a = 1; * public int b = 1; * public int c = 1; * }</pre>*/ public static abstract class AbsTuple { @Override public final int hashCode() throws RuntimeException { throw new RuntimeException(); } @Override public final boolean equals(@Nullable Object obj) throws RuntimeException { throw new RuntimeException(); } @Override protected final @NonNull Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } @Override public final @NonNull String toString() throws RuntimeException { throw new RuntimeException(); } } /** 継承例:2つのメンバ変数を持つ汎用タプル、Pairクラスのようなもの。推奨しない使い方 */ public static final class Tuple2<A, B> extends AbsTuple { public A a; public B b; } public static @NonNull Tuple2<String, String> getExample1(){ Tuple2<String, String> ret = new Tuple2<>(); ret.a = "this is a a"; ret.b = "this is a b"; return ret; } /** 例:メソッド専用のタプル。勘違いが少なく、定義に柔軟性がある。 */ public static final class ExampleTuple extends AbsTuple { public final @NonNull String first; public final @NonNull String second; public ExampleTuple(@NonNull String first, @NonNull String second) { this.first = first; this.second = second; } } public static @NonNull ExampleTuple getExample2(){ return new ExampleTuple("this is a first", "this is a second"); }
目的外の使用を阻止するため、あえてObjectメソッドの禁止という強い制限を設けている。
なんでもできるというのは一見便利だが、不便なことも多いと私は考える。