Определение параметров формального типа Java (Generics) - PullRequest
8 голосов
/ 11 декабря 2008

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

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

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

public final class MyClass<T extends Number> {
    // Implementation omitted
}

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

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

Ура, Дон

Ответы [ 5 ]

11 голосов
/ 11 декабря 2008

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

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

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
4 голосов
/ 12 декабря 2008

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

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) {
        //...
    }
}

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

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

2 голосов
/ 12 декабря 2008

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

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

0 голосов
/ 12 декабря 2013

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

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

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

0 голосов
/ 11 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...