Кодирование типа дженериков

У меня есть немного странная проблема с Java-дженериками. На самом деле это может быть не проблема, и мне может быть только, что я пытаюсь неправильно использовать дженерики в дизайне. Я не буду давать подробные сведения о приложении (это не имеет значения и скучно).

Я создал небольшой фрагмент, который отражает суть проблемы.

Существует интерфейс производителя, который выглядит так.

public interface Producer<p><code>{
public P produce(); 
}</code>
</p><p>Существует реализация этого интерфейса, которая выглядит как</p>
<pre class="prettyprint linenums">public class IntegerProducer<p> implements Producer</p><p><code>{
@Override
public P produce() {
 return (P)new Integer(10);
}
}</code>
</p><p>То, что мне действительно нужно делать в методе создания, - это что-то вроде</p>
<pre class="prettyprint linenums">if (P instanceOf Integer) return (P)new Integer(10);
else throw new Exception("Something weird happened in the client app");

Теперь, конечно, P instanceOf Integer не будет работать. Но если у вас есть суть того, что я пытаюсь сделать, не могли бы вы поделиться решением.

Спасибо за помощь.

Разъяснение 1: Проблема не в том, что я хочу вернуть Integer только. Проблема в том, что в функции produ() мне нужно проверить тип генериков, используемых клиентской программой, и изменить поведение функции на основе этого. Дело не в том, что я хочу ограничить тип генериков, используемых для определенного типа объекта (где я мог бы использовать подстановочные знаки), но мне нужно, чтобы функция произвела(), чтобы вести себя несколько иначе, в зависимости от типа Объекта, используемого в дженериках, клиентский код.

1 ответ

Как насчет:

public class IntegerProducer implements Producer<integer> {
 @Override
 public Integer produce() {
 return 10;
 }
}
</integer>

Поскольку ваш IntegerProducer имеет дело только с Integer, вам не нужно, чтобы он был общим. Затем вы можете написать:

Producer<integer> p = new IntegerProducer();
Integer i = p.produce();
</integer>

ИЗМЕНИТЬ

Следуя вашему комментарию, я думаю, что единственным способом было бы передать параметр класса:

public class Producer<t> {
 public static void main(String[] args) throws InterruptedException {
 Producer<integer> t1 = new Producer<> ();
 Producer<string> t2 = new Producer<> ();
 System.out.println(t1.get(Integer.class)); //prints 10
 System.out.println(t1.get(String.class)); //does not compile
 System.out.println(t2.get(String.class)); //throws exception
 }
 public T get(Class<t> c) {
 if (c == Integer.class) {
 return (T) (Object) 10;
 }
 throw new UnsupportedOperationException();
 }
}
</t></string></integer></t>

В качестве альтернативы вы можете передать его в конструкторе (стратегия, используемая, например, EnumSets и EnumMaps):

public class Producer<t> {
 public static void main(String[] args) throws InterruptedException {
 Producer<integer> t1 = new Producer<> (Integer.class);
 Producer<integer> t1 = new Producer<> (String.class); //does not compile
 Producer<string> t2 = new Producer<> (String.class);
 System.out.println(t1.get()); //prints 10
 System.out.println(t2.get()); //throws exception
 }
 private final Class<t> c;
 public Producer(Class<t> c) {
 this.c = c;
 }
 public T get() {
 if (c == Integer.class) {
 return (T) (Object) 10;
 }
 throw new UnsupportedOperationException();
 }
}
</t></t></string></integer></integer></t>

Это явно загромождает код, и я лично пересмотрю дизайн, чтобы избежать такой ситуации.

licensed under cc by-sa 3.0 with attribution.