Что такое типы raw в Java и почему я часто слышу, что они не должны использоваться в новом коде?
blockquote>Необработанные типы - это древняя история Java язык. В начале были
Collections
, и они больше не держалиObjects
и ничего меньше. Каждая операция наCollections
требовала отличных отObject
желаемого типа.List aList = new ArrayList(); String s = "Hello World!"; aList.add(s); String c = (String)aList.get(0);
Хотя это продолжалось большую часть времени, произошли ошибки
List aNumberList = new ArrayList(); String one = "1";//Number one aNumberList.add(one); Integer iOne = (Integer)aNumberList.get(0);//Insert ClassCastException here
Старый нетривиальные коллекции не могли обеспечить безопасность типов, поэтому программисту приходилось запоминать то, что он хранил в коллекции. Генераторы, изобретенные, чтобы обойти это ограничение, разработчик объявит сохраненный тип один раз, и компилятор сделает это вместо этого.
List
aNumberList = new ArrayList (); aNumberList.add("one"); Integer iOne = aNumberList.get(0);//Compile time error String sOne = aNumberList.get(0);//works fine Для сравнения:
// Old style collections now known as raw types List aList = new ArrayList(); //Could contain anything // New style collections with Generics List
aList = new ArrayList (); //Contains only Strings Более сложный Интерфейс Compareable:
//raw, not type save can compare with Other classes class MyCompareAble implements CompareAble { int id; public int compareTo(Object other) {return this.id - ((MyCompareAble)other).id;} } //Generic class MyCompareAble implements CompareAble
{ int id; public int compareTo(MyCompareAble other) {return this.id - other.id;} } Обратите внимание, что невозможно реализовать интерфейс
CompareAble
сcompareTo(MyCompareAble)
с необработанными типами. Почему вы не должны их использовать:
- Любое
Object
, хранящееся вCollection
, должно быть выполнено до его использования- Использование обобщений позволяет проверять время компиляции
- Использование исходных типов - это то же самое, что и сохранение каждого значения как
Object
Что делает компилятор: Дженерики обратно совместимы, они используют одни и те же классы java, типы делают.
List
someStrings = new ArrayList (); someStrings.add("one"); String one = someStrings.get(0); Будет скомпилирован как:
List someStrings = new ArrayList(); someStrings.add("one"); String one = (String)someStrings.get(0);
Это тот же код, который вы бы написали, если вы использовали исходные типы напрямую. Думаю, я не уверен, что происходит с интерфейсом
CompareAble
, я предполагаю, что он создает две функцииcompareTo
, одна из которых принимаетMyCompareAble
, а другая принимаетObject
и передает ее первой после ее литья.Каковы альтернативы сырым типам: используйте generics
Это потому, что вычисления в правой части присваивания выполняются в виде целочисленного типа. И это переполняет целое число
Вы можете исправить это с помощью:
public const long MAXIMUM_RANGE_MAGNITUDE = int.MaxValue + (long)1; // or 1L
Путем литья хотя бы одного из операндов в long
Причина, по которой вы получаете ошибка указана в спецификациях C #.
См. раздел C # Specification Section 4.1.5 (Integral types)
Для двоичных файлов +, -, *, /,%, & amp; , ^, |, ==,! =,>, & lt ;,> = и & lt; = операторы, операнды преобразуются в тип T, где T является первым из int, uint, long и ulong, который может полностью представляют все возможные значения обоих операндов. Затем операция выполняется с использованием точности типа T, а типом результата является T (или bool для реляционных операторов). Недопустимо, чтобы один операнд имел длинный тип, а другой - тип ulong с бинарными операторами.
blockquote>В вашем случае, поскольку оба операнда сложения могут быть представлены в
int
, поэтому вычисление выполняется в целочисленном типе. Явное литье одного из операндов вlong
приведет к результатуlong
и, следовательно, не приведет к ошибке переполнения.
Я думаю, что это связано с вычислением значения int.MaxValue + 1
перед , сделанным актом long
. Конечно, длинные могут удерживать значение, но поскольку вы выполняете целочисленное добавление, невозможно сохранить целочисленное значение int.MaxValue + 1
в int до тех пор, пока не будет выполнено литье.
Ваш код на самом деле выглядит следующим образом:
(long)(int.MaxValue + 1)
Но поскольку .Net framework имеет встроенное неявное преобразование между int и long, вам не нужно явно помещать листинг в ваш код.
Итак, во-первых, эта часть кода выполняется:
int.MaxValue + 1
, и результатом этой операции является значение int
, которое вызывает и исключает переполнение. Таким образом, ваш код даже не имеет возможности начать преобразование из int в long.
try
public const long MAXIMUM_RANGE_MAGNITUDE = (long)int.MaxValue + 1L;
Приведите значение константы в длинное.
public const long MAXIMUM_RANGE_MAGNITUDE = (long) int.MaxValue + 1;
+ 1L;
– Tim Schmelter 31 January 2014 в 21:46