質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

846閲覧

[Java] ジェネリクスとシングルトン

yama_da

総合スコア73

Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

2グッド

3クリップ

投稿2017/09/25 04:18

以下の例ように(疑似コードです)、一種類の型を扱うシングルトンクラスを、ジェネリクスを用いて複数種類分用意したいのですが、どのように実現すれば良いのでしょうか?
代替案でも構いません、回答よろしくお願いします。

public static void main(String[] args) { /** * * GenericsSingleton<T> はT型のオブジェクトを扱うシングルトンクラス. * * strSingleton1 と strSingleton2 は同じインスタンス, * intSingleton と strSingleton1,2 は違うインスタンス. */ GenericsSingleton<String> strSingleton1 = GenericsSingleton<String>.getInstance(); GenericsSingleton<String> strSingleton2 = GenericsSingleton<String>.getInstance(); GenericsSingleton<Integer> intSingleton = GenericsSingleton<Integer>.getInstance(); }
iwamoto_takaaki, so87👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

Javaのジェネリクスは後付けだったこともあって、コンパイルしたバイトコード上では型情報が消えてしまいます。そのため、コンパイル後にはGenericsSingleton<String>.getInstance()GenericsSingleton<String>.getInstance()の区別がつきません。

ということで、「型ごとに別インスタンスとしたい」のであれば、getInstance(Class<T> clazz)のようにClassを引数にとって、それで振り分けをやるしかないと思います。

投稿2017/09/25 04:31

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ご参考までに可変長引数使うと、引数無しでも関数の呼び出し可能です。
やっていることはmaisumakunサンと同じで、
getInstanceでジェネリクスのクラス毎に振り分けです。

public class GenericsSingleton<T> { public static <T> GenericsSingleton<T> getInstance(T... dummy) { System.out.println(dummy.getClass()); // ex) class毎にmapからget、なければnewして、put return new GenericsSingleton<T>();// map.get(dummy.getClass()); } public static void main(String[] args) { GenericsSingleton<String> test = GenericsSingleton.getInstance(); Integer obj = null; GenericsSingleton.getInstance(obj); GenericsSingleton.getInstance(null);// nullpo } }

一番最後だけヌルポしますので、ご注意を。

投稿2017/09/25 06:14

szk.

総合スコア1400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2017/09/25 06:36

dummyは配列になるため、getClassすると配列型のClassを返すことになります。 getComponentTypeが妥当ですね。
szk.

2017/09/25 07:25

おっ、勉強になります。 確かに「dummy.getClass().getComponentType()」のほうがデバッグした時に分かりやすいですね。 最悪、クラス名でif文も組めますし。
yama_da

2017/09/26 05:42

回答ありがとうございます。 可変長引数を使うとなぜ引数なしでもTの型が決まるのですか?型推論的なことが起こるのでしょうか?
so87

2017/09/26 10:49

可変長引数dummyの実態は配列となるのですが、Javaの配列は共変という性質上、自身の型情報をもっており、getComponentTypeで配列の型情報を取り出してごにょごにょする、という仕組みかと思います。
yama_da

2017/09/29 23:32

返信が遅くなってすみません。 ありがとうございます、参考になりました。
guest

0

java

1import java.util.HashMap; 2import java.util.Map; 3 4public class Q93782 { 5 6 public static void main(String[] args) { 7 GenericsSingleton<String> s1 = GenericsSingleton.getInstance(String.class); 8 GenericsSingleton<String> s2 = GenericsSingleton.getInstance(String.class); 9 GenericsSingleton<Integer> i1 = GenericsSingleton.getInstance(Integer.class); 10 GenericsSingleton<Integer> i2 = GenericsSingleton.getInstance(1); 11 System.out.println("s1 == s2 :" + (s1 == s2)); 12 System.out.println("i1 == i2 :" + (i1 == i2)); 13 System.out.println(GenericsSingleton.instances); 14 } 15 16 static class GenericsSingleton<T> { 17 static Map<Class<?>, GenericsSingleton<?>> instances = new HashMap<>(); 18 19 @SuppressWarnings("unchecked") 20 public static <T> GenericsSingleton<T> getInstance(Class<T> clazz) { 21 return (GenericsSingleton<T>) instances.computeIfAbsent(clazz, c -> new GenericsSingleton<>()); 22 } 23 24 @SuppressWarnings("unchecked") 25 public static <T> GenericsSingleton<T> getInstance(T... dummy) { 26 return (GenericsSingleton<T>) getInstance(dummy.getClass().getComponentType()); 27 } 28 } 29 30} 31

面白そうだったので作ってみました。2個目のgetInstanceはszk.さんのを載せてみました。
どうにも不格好さが抜けない。

投稿2017/09/25 14:59

編集2017/09/25 15:03
swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

so87

2017/09/26 03:25

szk.さんの手法ならString.classやInteger.classを引数として渡す必要はないので サンプルコードとしてならs2のほうは引数なしで呼び出したほうが適切じゃないでしょうか。 GenericsSingleton<String> s2 = GenericsSingleton.getInstance();
swordone

2017/09/26 05:49

可変長引数なのに引数を渡さないこと前提というのが嫌だったもので…。
szk.

2017/09/27 04:37

意味のない引数がイヤだという気持ちはとてもわかります。 大~中規模案件でpubicメソッドだったら、間違いなく固定の引数入れさせます。 ただジェネリクスで指定したクラスをわざわざ引数に入れるのも、 なんか流行に逆らってる気がして、個人的には気持ち悪いです。 ダイアモンド演算子みたいにjavaがどーにか拡張してくれればいいんですけど。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問