Ограничение дженериков с 'супер' ключевым словом

Если вы хотите добиться этого с помощью регулярного выражения, вы можете использовать.

^(\d*\.)?\d+$

Демо

Но учтите, что вы также можете использовать Decimal.TryParse. Вы можете прочитать больше о Decimal.TryParse здесь

55
задан Paul Bellora 18 August 2013 в 16:18
поделиться

2 ответа

super для привязки параметра именованного типа (например, ) в отличие от подстановочного символа (например, ) является НЕЗАКОННЫМ просто потому, что даже если он разрешен, он не будет делать то, что вы надеялся, что это сработает, потому что, поскольку Объект является конечным супер из всех ссылочных типов, а все является Объектом , , по сути, нет никаких ограничений .

В вашем конкретном примере, поскольку любой массив ссылочного типа является Object [] (по ковариации массива Java), его можно использовать в качестве аргумента для S [] toArray (S [] a) (если такая привязка допустима) во время компиляции, и это не предотвратит ArrayStoreException во время выполнения.

Вы пытаетесь предложить следующее:

List<Integer> integerList;

и учитывая это гипотетическое супер , привязанное к toArray :

<S super T> S[] toArray(S[] a) // hypothetical! currently illegal in Java

компилятор должен разрешать только следующие для компиляции:

integerList.toArray(new Integer[0]) // works fine!
integerList.toArray(new Number[0])  // works fine!
integerList.toArray(new Object[0])  // works fine!

и никаких других аргументов типа массива (поскольку Integer имеет только эти 3 типа как super ). То есть вы пытаетесь предотвратить компиляцию:

integerList.toArray(new String[0])  // trying to prevent this from compiling

, потому что по вашему аргументу String не является super из Integer . Однако , Объект является супер из Integer , а String [] является объектом [] , поэтому компилятор по-прежнему позволит компилировать вышеупомянутое, даже если гипотетически вы можете выполнить !

Таким образом, следующий по-прежнему будет компилироваться (так же, как и сейчас), а ArrayStoreException во время выполнения не может быть предотвращено какой-либо проверкой времени компиляции с использованием универсального границы типов:

integerList.toArray(new String[0])  // compiles fine!
// throws ArrayStoreException at run-time

Обобщения и массивы не смешиваются, и это одно из многих мест, где это показано.


Пример без массива

Снова допустим, что у вас есть это объявление общего метода:

<T super Integer> void add(T number) // hypothetical! currently illegal in Java

И у вас есть эти объявления переменных:

Integer anInteger
Number aNumber
Object anObject
String aString

Ваше намерение с (если это разрешено), это то, что он должен разрешать добавить (anInteger) и добавить (aNumber) , и, конечно, добавить (anObject) , но НЕ добавить (aString) . Что ж, String - это объект , поэтому add (aString) все равно будет компилироваться.


См. Также

Связанные вопросы

О правилах набора обобщенных типов: