2008-12-11 2 views
8

Я хотел бы определить общий тип, чей фактический тип параметра может быть толькоJava формальное определение типа параметра (дженериков)

  1. Один из числовых примитивных классов-оболочек (Long, Integer, Float, Double)
  2. String

я могу выполнить первое требование с определением, как этот

Но я не могу понять, как встретить их обоих. Я подозреваю, что это на самом деле не возможно, потому что AFAIK нет способа указать «или» семантику при определении формального параметра типа, хотя можно указать «и» семантика, используя определение, такие как

public final class MyClass<T extends Runnable & Serializable > { 
    // Implementation omitted 
} 

Приветствия, Дон

+0

Тип стирания вернет его обратно на объект, если он существует. – Loki 2008-12-11 20:48:50

ответ

0

Интересный вопрос, это немного ошеломило меня. Однако, по-видимому, это невозможно. Я попробовал несколько разных хаков, никто не работает.

11

Java generics не поддерживает типы объединения (этот параметр может быть A ИЛИ B).

В отношении соответствующей заметки, которая может представлять интерес для некоторых, она поддерживает несколько границ, если вы хотите применить несколько ограничений. Вот пример из JDK упоминается в Java generics tutorial:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) 
+1

Разве это не плохой пример (я вижу, это от СОЛНЦА, а не от твоего)? > совпадает с >, не так ли? ничего не значит. – Markus 2008-12-12 18:44:06

2

Хотя дженерики не будет работать здесь, базовый тип с производными типами для Number и String воли. Так как общий тип удалялся бы до Object, любая функциональность, которую вы могли бы там положить, может идти в абстрактном базовом классе. Для получения значения вам, вероятно, понадобится только тип-тип доступа для подкласса.

Кроме того, будьте осторожны с классом Number. Это не ограничивается боксированием примитивных типов, так как любой может расширить его. — например, BigInteger.

4

Вы можете использовать фабричные методы для всех поддерживаемых типов и сделать конструктор частным/защищенным. Вы должны установить общий тип в конструкторе все равно так, что это имеет смысл, так что вы, вероятно, можете кодировать это следующим образом:

public final class MyClass<T> { 
    public static MyClass<Integer> newInstance(int i) { 
     return new MyClass<Integer>(i); 
    } 
    public static MyClass<String> newInstance(String s) { 
     return new MyClass<String>(s); 
    } 
    //More factory methods... 

    protected MyClass(T obj) { 
     //... 
    } 
} 

Или, если вы не хотите, параметра конструктора, что-то вроде этого: общественного финала class MyClass { public static MyClass newIntegerInstance() { return new MyClass(); } // ...}

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

0

Может быть, вы могли бы сделать то, что следующим образом:

  1. Сделать MyClass<T> пакетный-класс по умолчанию, невидимый для других компонентов, или, по крайней мере, с только пакетом, по умолчанию ctors, так что она не может расширить или инстанцирована вне пакет.
  2. Создание двух общественных классов в пакете MyClass<T>:
MyNumericClass<T extends Number> extends MyClass<T> 
MyStringClass extends MyClass<String> 

Таким образом, все подклассы MyClass будут ограничены тем, параметризованных с номером подкласса или String.

Смежные вопросы