Что такое необработанный тип и почему мы не должны его использовать?


663

Вопросов:

  • Что такое необработанные типы в Java, и почему я часто слышу, что они не должны использоваться в новом коде?
  • Какая альтернатива, если мы не можем использовать необработанные типы, и как это лучше?

Java-учебники по-прежнему используют JComboBox, который вызывает это предупреждение. Какая версия выпадающего списка не вызовет это предупреждение? docs.oracle.com/javase/tutorial/uiswing/components/…
SuperStar,

1
Обратите внимание, что причина существования необработанных типов заключается в обратной совместимости с Java 1.4 и более ранними версиями, у которых вообще не было обобщений.
Джеспер

Ответы:


745

Что такое сырой тип?

Спецификация языка Java определяет необработанный тип следующим образом:

JLS 4.8 Необработанные типы

Необработанный тип определяется как один из:

  • Тип ссылки, который формируется путем взятия имени объявления универсального типа без сопровождающего списка аргументов типа.

  • Тип массива, тип элемента которого является необработанным типом.

  • Не- staticтипа члена исходного типа R, не унаследованный от суперкласса или суперинтерфейса R.

Вот пример для иллюстрации:

public class MyType<E> {
    class Inner { }
    static class Nested { }

    public static void main(String[] args) {
        MyType mt;          // warning: MyType is a raw type
        MyType.Inner inn;   // warning: MyType.Inner is a raw type

        MyType.Nested nest; // no warning: not parameterized type
        MyType<Object> mt1; // no warning: type parameter given
        MyType<?> mt2;      // no warning: type parameter given (wildcard OK!)
    }
}

Здесь MyType<E>- параметризованный тип ( JLS 4.5 ). Обычно в разговорной речи называют этот тип просто MyTypeдля краткости, но формально это имя MyType<E>.

mtимеет необработанный тип (и генерирует предупреждение о компиляции) по первому пункту в приведенном выше определении; innтакже имеет необработанный тип по третьему пункту.

MyType.Nestedне параметризованный тип, хотя это тип члена параметризованного типа MyType<E>, потому что это static.

mt1и mt2оба объявлены с фактическими параметрами типа, поэтому они не являются необработанными типами.


Что такого особенного в необработанных типах?

По сути, необработанные типы ведут себя так же, как и до появления дженериков. То есть, следующее является полностью законным во время компиляции.

List names = new ArrayList(); // warning: raw type!
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // not a compilation error!

Приведенный выше код работает просто отлично, но предположим, что у вас также есть следующее:

for (Object o : names) {
    String name = (String) o;
    System.out.println(name);
} // throws ClassCastException!
  //    java.lang.Boolean cannot be cast to java.lang.String

Теперь мы сталкиваемся с проблемами во время выполнения, потому что namesсодержит что-то, что не является instanceof String.

Предположительно, если вы хотите namesсодержать только String, возможно , вы все еще могли бы использовать необработанный тип и вручную проверять каждый add сам, а затем вручную приводить к Stringкаждому элементу из names. Еще лучше , хотя НЕ использовать необработанный тип и позволить компилятору сделать всю работу за вас , используя всю мощь Java-дженериков.

List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // compilation error!

Конечно, если вы НЕ хотите , namesчтобы позволить Boolean, то вы можете объявить его как List<Object> namesи приведенный выше код будет компилироваться.

Смотрите также


Чем необработанный тип отличается от использования в <Object>качестве параметров типа?

Ниже приводится цитата из Effective Java 2nd Edition, пункт 23. Не используйте необработанные типы в новом коде :

В чем разница между необработанным типом Listи параметризованным типом List<Object>? Грубо говоря, первый отказался от проверки универсального типа, в то время как последний явно сказал компилятору, что он способен содержать объекты любого типа. Хотя вы можете передавать List<String>параметр типа List, вы не можете передать его параметру типа List<Object>. Существуют правила подтипов для обобщений, и List<String>это подтип необработанного типа List, но не параметризованного типа List<Object>. Как следствие, вы теряете безопасность типов, если вы используете сырой тип как List, но не если вы используете параметризованный тип какList<Object> .

Чтобы проиллюстрировать это, рассмотрим следующий метод, который принимает List<Object>и добавляет a new Object().

void appendNewObject(List<Object> list) {
   list.add(new Object());
}

Обобщения в Java инвариантны. A List<String>не является a List<Object>, поэтому следующее генерирует предупреждение компилятора:

List<String> names = new ArrayList<String>();
appendNewObject(names); // compilation error!

Если бы вы объявили, appendNewObjectчто в Listкачестве параметра принимается необработанный тип , он скомпилируется, и поэтому вы потеряете безопасность типов, которую вы получаете от обобщений.

Смотрите также


Чем необработанный тип отличается от использования <?>в качестве параметра типа?

List<Object>и List<String>т. д. все List<?>, так что может быть заманчиво просто сказать, что они просто Listвместо. Тем не менее, есть существенное отличие: поскольку a List<E>определяет только add(E), вы не можете добавить любой произвольный объект в a List<?>. С другой стороны, поскольку необработанный тип Listне имеет безопасности типов, вы можете получить addчто угодно List.

Рассмотрим следующий вариант предыдущего фрагмента:

static void appendNewObject(List<?> list) {
    list.add(new Object()); // compilation error!
}
//...

List<String> names = new ArrayList<String>();
appendNewObject(names); // this part is fine!

Компилятор прекрасно защитил вас от возможного нарушения неизменности типов List<?>! Если бы вы объявили параметр как необработанный тип List list, то код скомпилировался бы, и вы нарушили бы инвариант типа List<String> names.


Необработанный тип - это стирание этого типа.

Вернуться к JLS 4.8:

В качестве типа можно использовать стирание параметризованного типа или стирание типа массива, тип элемента которого является параметризованным типом. Такой тип называется необработанным типом .

[...]

Суперклассы (соответственно, суперинтерфейсы) необработанного типа являются стиранием суперклассов (суперинтерфейсов) любой из параметризаций универсального типа.

Тип конструктора, метода экземпляра или неполя staticполя необработанного типа, Cкоторый не унаследован от его суперклассов или суперинтерфейсов, является необработанным типом, который соответствует удалению его типа в общем объявлении, соответствующем C.

Проще говоря, когда используются сырой типа, конструкторы, методы экземпляра и не- staticполей также удаляется .

Возьмите следующий пример:

class MyType<E> {
    List<String> getNames() {
        return Arrays.asList("John", "Mary");
    }

    public static void main(String[] args) {
        MyType rawType = new MyType();
        // unchecked warning!
        // required: List<String> found: List
        List<String> names = rawType.getNames();
        // compilation error!
        // incompatible types: Object cannot be converted to String
        for (String str : rawType.getNames())
            System.out.print(str);
    }
}

Когда мы используем сырье MyType, оно также getNamesстирается, так что оно возвращает сырье List!

JLS 4.6 продолжает объяснять следующее:

Стирание типа также отображает сигнатуру конструктора или метода в сигнатуру, которая не имеет параметризованных типов или переменных типа. Стирание сигнатуры конструктора или метода s- это сигнатура, состоящая из того же имени, что sи стирание всех типов формальных параметров, приведенных в s.

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

Удаление подписи универсального метода не имеет параметров типа.

В следующем сообщении об ошибке содержатся некоторые мысли Маурицио Симадамора, разработчика компилятора, и Алекса Бакли, одного из авторов JLS, о причинах такого поведения: https://bugs.openjdk.java.net/browse / JDK-6400189 . (Короче говоря, это упрощает спецификацию.)


Если это небезопасно, почему разрешено использовать необработанный тип?

Вот еще одна цитата из JLS 4.8:

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

Effective Java 2nd Edition также имеет следующее:

Учитывая, что вы не должны использовать необработанные типы, почему разработчики языка разрешили это? Для обеспечения совместимости.

Платформа Java собиралась вступить во второе десятилетие, когда были представлены дженерики, и существовало огромное количество Java-кода, который не использовал дженерики. Было сочтено критически важным, чтобы весь этот код оставался законным и мог взаимодействовать с новым кодом, который использует дженерики. Должно быть допустимо передавать экземпляры параметризованных типов в методы, которые были разработаны для использования с обычными типами, и наоборот. Это требование, известное как совместимость миграции , привело к принятию решения о поддержке необработанных типов.

Таким образом, необработанные типы никогда не должны использоваться в новом коде. Вы должны всегда использовать параметризованные типы .


Есть ли исключения?

К сожалению, из-за непатентованного универсального кода Java есть два исключения, где необработанные типы должны использоваться в новом коде:

  • Литералы класса, например List.class, неList<String>.class
  • instanceofоперанд, например o instanceof Set, неo instanceof Set<String>

Смотрите также


16
Что вы имеете в виду, что "дженерики Java не являются reified"?
Карл Дж

7
Во втором исключении синтаксис o instanceof Set<?>также разрешен, чтобы избежать необработанного типа (хотя это только поверхностно в этом случае).
Пол Беллора

1
Необработанные типы очень полезны и сокращают шаблонный код в случае поиска JNDI для bean-компонента, расширяющего интерфейс. Это устраняет необходимость написания nудаленных компонентов для каждого реализующего класса с идентичным кодом.
djmj

8
«Нерасположенный» - это еще один способ сказать, что они стерты. Компилятор знает, что такое общие параметры, но эта информация не передается в сгенерированный байт-код. JLS требует, чтобы литералы класса не имели параметров типа.
Эрик Дж. Хагстрем

2
@ OldCurmudgeon Это интересно. Я имею в виду, что официально это ни то , ни другое , потому что литерал класса определен просто TypeName.class, где TypeNameпростой идентификатор ( jls ). Говоря гипотетически, я думаю, что на самом деле это тоже может быть. Может быть, в качестве подсказки, List<String>.classэто вариант, который JLS специально вызывает ошибку компилятора, поэтому, если они когда-нибудь добавят ее в язык, я ожидаю, что это тот, который они используют.
Radiodef

62

Что такое необработанные типы в Java, и почему я часто слышу, что они не должны использоваться в новом коде?

Raw-типы - это древняя история языка 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<String> aNumberList = new ArrayList<String>();
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<String> aList = new ArrayList<String>(); //Contains only Strings

Более сложный сравниваемый интерфейс:

//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<MyCompareAble>
{
   int id;
   public int compareTo(MyCompareAble other)
   {return this.id - other.id;}
}

Обратите внимание, что невозможно реализовать CompareAbleинтерфейс compareTo(MyCompareAble)с необработанными типами. Почему вы не должны использовать их:

  • Все, что Objectхранится в a Collection, должно быть разыграно перед использованием.
  • Использование обобщений позволяет проверять время компиляции
  • Использование необработанных типов аналогично сохранению каждого значения Object

Что делает компилятор: Generics обратно совместимы, они используют те же классы Java, что и необработанные типы. Магия происходит в основном во время компиляции.

List<String> someStrings = new ArrayList<String>();
someStrings.add("one");
String one = someStrings.get(0);

Будет скомпилировано как:

List someStrings = new ArrayList();
someStrings.add("one"); 
String one = (String)someStrings.get(0);

Это тот же код, который вы написали бы, если бы использовали непосредственные типы. Хотя я не уверен, что происходит с CompareAbleинтерфейсом, я предполагаю, что он создает две compareToфункции, одну из которых принимает a, MyCompareAbleа другую принимает Objectи передает его первой после приведения.

Какие альтернативы необработанным типам: Используйте дженерики


30

Необработанный тип - это имя универсального класса или интерфейса без аргументов типа. Например, учитывая общий класс Box:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

Чтобы создать параметризованный тип Box<T>, вы предоставляете фактический аргумент типа для параметра формального типа T:

Box<Integer> intBox = new Box<>();

Если фактический аргумент типа опущен, вы создаете необработанный тип Box<T>:

Box rawBox = new Box();

Следовательно, Boxэто необработанный тип универсального типа Box<T>. Однако неуниверсальный класс или тип интерфейса не является необработанным типом.

Необработанные типы отображаются в устаревшем коде, потому что многие классы API (такие как классы Collections) не были универсальными до JDK 5.0. При использовании необработанных типов вы, по сути, получаете пре-родовое поведение - a Boxдает вам Objects. Для обратной совместимости допускается присвоение параметризованного типа его необработанному типу:

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;               // OK

Но если вы назначите необработанный тип параметризованному типу, вы получите предупреждение:

Box rawBox = new Box();           // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox;     // warning: unchecked conversion

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

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);  // warning: unchecked invocation to set(T)

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

Раздел Erasure Type содержит больше информации о том, как компилятор Java использует необработанные типы.

Непроверенные сообщения об ошибках

Как упоминалось ранее, при смешивании устаревшего кода с универсальным кодом вы можете столкнуться с предупреждающими сообщениями, подобными следующим:

Примечание: Example.java использует непроверенные или небезопасные операции.

Примечание: Перекомпилируйте с -Xlint: не проверено для деталей.

Это может произойти при использовании старого API, который работает с необработанными типами, как показано в следующем примере:

public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }

    static Box createBox(){
        return new Box();
    }
}

Термин «непроверенный» означает, что у компилятора недостаточно информации о типе, чтобы выполнить все проверки типов, необходимые для обеспечения безопасности типов. По умолчанию предупреждение «unchecked» отключено, хотя компилятор дает подсказку. Чтобы увидеть все «непроверенные» предупреждения, перекомпилируйте с -Xlint: unchecked.

Перекомпиляция предыдущего примера с -Xlint: unchecked открывает следующую дополнительную информацию:

WarningDemo.java:4: warning: [unchecked] unchecked conversion
found   : Box
required: Box<java.lang.Integer>
        bi = createBox();
                      ^
1 warning

Чтобы полностью отключить непроверенные предупреждения, используйте флаг -Xlint: -unchecked. @SuppressWarnings("unchecked")Аннотацию подавляет непроверенные предупреждения. Если вы не знакомы с @SuppressWarningsсинтаксисом, см. Аннотации.

Первоначальный источник: Java Tutorials


21

«Необработанный» тип в Java - это класс, который не является универсальным и имеет дело с «необработанными» объектами, а не с типизированными параметрами универсального типа.

Например, до того как Java-дженерики стали доступны, вы должны использовать класс коллекции следующим образом:

LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);

Когда вы добавляете свой объект в список, его не волнует, какой это тип объекта, и когда вы получаете его из списка, вы должны явно привести его к ожидаемому типу.

Используя дженерики, вы удаляете «неизвестный» фактор, потому что вы должны явно указать, какой тип объектов может идти в списке:

LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);

Обратите внимание, что при использовании дженериков вам не нужно приводить объект, полученный из вызова get, коллекция предопределена для работы только с MyObject. Этот факт является основным движущим фактором для дженериков. Это превращает источник ошибок времени выполнения во что-то, что можно проверить во время компиляции.


3
В частности, необработанный тип - это то, что вы получаете, когда просто опускаете параметры типа для универсального типа. Необработанные типы в действительности были только функцией обратной совместимости и потенциально могут быть удалены. Вы можете получить похожее поведение, используя? параметры подстановочных знаков.
Джон Флатнесс

@zerocrates: похожие, но разные! Использование по- ?прежнему предлагает безопасность типов. Я покрыл это в своем ответе.
полигенасмазочные материалы

19
 private static List<String> list = new ArrayList<String>();

Вы должны указать тип-параметра.

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

Listопределяется поддержки дженериков: public class List<E>. Это позволяет выполнять многие безопасные для типов операции, которые проверяются во время компиляции.


3
Теперь заменен на алмазный вывод в Java 7 -private static List<String> list = new ArrayList<>();
Ян Кэмпбелл

14

Что такое необработанный тип и почему я часто слышу, что его не следует использовать в новом коде?

«Необработанный тип» - это использование универсального класса без указания аргумента (ов) типа для его параметризованного типа (типов), например, с использованием Listвместо List<String>. Когда дженерики были введены в Java, несколько классов были обновлены для использования дженериков. Использование этих классов в качестве «необработанного типа» (без указания аргумента типа) позволило устаревшему коду все еще компилироваться.

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

Какая альтернатива, если мы не можем использовать необработанные типы, и как это лучше?

Предпочтительной альтернативой является использование обобщенных классов по назначению - с подходящим аргументом типа (например List<String>). Это позволяет программисту более конкретно указывать типы, сообщает будущим разработчикам больше смысла о предполагаемом использовании переменной или структуры данных, а также позволяет компилятору обеспечивать лучшую безопасность типов. Вместе эти преимущества могут улучшить качество кода и предотвратить появление некоторых ошибок кодирования.

Например, для метода, в котором программист хочет убедиться, что переменная List с именем 'names' содержит только строки:

List<String> names = new ArrayList<String>();
names.add("John");          // OK
names.add(new Integer(1));  // compile error

1
Ах, так соблазнительно скопировать polygenelubricantsссылки «необработанного типа» из stackoverflow.com/questions/2770111/… в мой собственный ответ, но я полагаю, что оставлю их для использования в своем собственном ответе.
Берт Ф.

1
да, я, по сути, копировал и вставлял этот сегмент везде, где люди используют необработанные типы в stackoverflow, и в конце концов решил просто иметь один вопрос, на который можно ссылаться с этого момента. Я надеюсь, что это хороший вклад для сообщества.
полигенасмазочные материалы

1
@polygenelubricants, которые я заметил - мы задали одни и те же вопросы :-)
Берт Ф

1
@ ha9u63ar: Действительно. В общем краткие и простые ответы, по крайней мере, так же хороши, как и длинные и общепринятые.
displayName

Что такое "сильнее сироп"?
carloswm85

12

Компилятор хочет, чтобы вы написали это:

private static List<String> list = new ArrayList<String>();

потому что в противном случае вы можете добавить любой тип, который вам нравится list, делая создание экземпляров new ArrayList<String>()бессмысленным. Обобщения Java являются только функцией времени компиляции, поэтому созданный объект с new ArrayList<String>()радостью примет элементы Integerили JFrameэлементы, если они назначены для ссылки на «необработанный тип» List- сам объект ничего не знает о том, какие типы он должен содержать, только компилятор.


12

Здесь я рассматриваю несколько случаев, с помощью которых вы можете прояснить концепцию

1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();

Дело 1

ArrayList<String> arrэто ArrayListссылочная переменная с типом, Stringкоторая ссылается на ArralyListобъект типа String. Это означает, что он может содержать только объект типа String.

Это строгий, а Stringне необработанный тип, поэтому он никогда не выдаст предупреждение.

    arr.add("hello");// alone statement will compile successfully and no warning.

    arr.add(23);  //prone to compile time error.
     //error: no suitable method found for add(int)

Дело 2

В этом случае ArrayList<String> arrэто строгий тип, но ваш объект new ArrayList();является необработанным типом.

    arr.add("hello"); //alone this compile but raise the warning.
    arr.add(23);  //again prone to compile time error.
    //error: no suitable method found for add(int)

здесь arrстрогий тип. Таким образом, это приведет к ошибке времени компиляции при добавлении integer.

Предупреждение : - RawОбъект типа связан с Strictтипом ссылочной переменной ArrayList.

Дело 3

В этом случае ArrayList arrэто необработанный тип, но ваш объект new ArrayList<String>();является строгим типом.

    arr.add("hello");  
    arr.add(23);  //compiles fine but raise the warning.

Он добавит в него любой тип объекта, потому что arrэто необработанный тип.

Предупреждение : - StrictОбъект rawтипа ссылается на переменную, на которую ссылается тип.


8

Сырья типа является отсутствие в параметре типа при использовании универсального типа.

Сырье типа не следует использовать , поскольку это может привести к ошибкам во время выполнения, как и вставки doubleв то , что должно было быть Setв intс.

Set set = new HashSet();
set.add(3.45); //ok

При извлечении материала из Set, вы не знаете, что выходит. Давайте предположим, что вы ожидаете, что это все ints, к которому вы приводите Integer; исключение во время выполнения, когда doubleприходит 3.45.

Если к вашему параметру добавлен параметр типаSet , вы сразу получите ошибку компиляции. Эта упреждающая ошибка позволяет устранить проблему до того, как что-то взорвется во время выполнения (что сэкономит время и усилия).

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.

7

Вот еще один случай, когда необработанные типы будут кусать вас:

public class StrangeClass<T> {
  @SuppressWarnings("unchecked")
  public <X> X getSomethingElse() {
    return (X)"Testing something else!";
  }

  public static void main(String[] args) {
    final StrangeClass<String> withGeneric    = new StrangeClass<>();
    final StrangeClass         withoutGeneric = new StrangeClass();
    final String               value1,
                               value2;

    // Compiles
    value1 = withGeneric.getSomethingElse();

    // Produces compile error:
    // incompatible types: java.lang.Object cannot be converted to java.lang.String
    value2 = withoutGeneric.getSomethingElse();
  }
}

Как уже упоминалось в принятом ответе, вы теряете всю поддержку обобщений в коде необработанного типа. Каждый параметр типа преобразуется в его стирание (что в приведенном выше примере просто Object).


5

Что сказать, что ваш listесть Listиз unespecified объектов. То есть Java не знает, какие объекты находятся внутри списка. Затем, когда вы хотите перебрать список, вы должны привести каждый элемент, чтобы иметь доступ к свойствам этого элемента (в данном случае, String).

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

private static List<String> list = new ArrayList<String>();

4

учебная страница .

Необработанный тип - это имя универсального класса или интерфейса без аргументов типа. Например, учитывая общий класс Box:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

Чтобы создать параметризованный тип Box, вы предоставляете фактический аргумент типа для параметра формального типа T:

Box<Integer> intBox = new Box<>();

Если фактический аргумент типа опущен, вы создаете необработанный тип Box:

Box rawBox = new Box();

2

Избегайте необработанных типов

Необработанные типы относятся к использованию универсального типа без указания параметра типа.

Например ,

Список является необработанным типом, а List<String>является параметризованным типом.

Когда дженерики были представлены в JDK 1.5, необработанные типы были сохранены только для обеспечения обратной совместимости со старыми версиями Java. Хотя использование необработанных типов все еще возможно,

Их следует избегать :

  • Они обычно требуют приведения
  • Они не являются безопасными по типу, и некоторые важные виды ошибок будут появляться только во время выполнения
  • Они менее выразительны и не документируют себя так же, как параметризованные типы. Пример

    import java.util.*;
    
    public final class AvoidRawTypes {
    
    void withRawType() {
    
        //Raw List doesn't self-document, 
        //doesn't state explicitly what it can contain
    
        List stars = Arrays.asList("Arcturus", "Vega", "Altair");
    
        Iterator iter = stars.iterator();
    
        while (iter.hasNext()) {
    
            String star = (String) iter.next(); //cast needed
    
            log(star);
        }
    
    }
    
    void withParameterizedType() {
    
        List < String > stars = Arrays.asList("Spica", "Regulus", "Antares");
    
        for (String star: stars) {
    
            log(star);
        }
    
    }
    
    private void log(Object message) {
    
        System.out.println(Objects.toString(message));
    
    }
    
    }

Для справки : https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html


1

Я нашел эту страницу после того, как выполнил несколько типовых упражнений и получил точно такую ​​же загадку.

============== Я пошел из этого кода, как показано в примере ===============

public static void main(String[] args) throws IOException {

    Map wordMap = new HashMap();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator i = wordMap.entrySet().iterator(); i.hasNext();) {
        Map.Entry entry = (Map.Entry) i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

====================== К этому коду ========================

public static void main(String[] args) throws IOException {
    // replace with TreeMap to get them sorted by name
    Map<String, Integer> wordMap = new HashMap<String, Integer>();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator<Entry<String, Integer>> i = wordMap.entrySet().iterator(); i.hasNext();) {
        Entry<String, Integer> entry =   i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

}

================================================== =============================

Это может быть безопаснее, но понадобилось 4 часа, чтобы разобраться в философии ...


0

Сырые типы хороши, когда они выражают то, что вы хотите выразить.

Например, функция десериализации может возвращать a List, но она не знает тип элемента списка. Так Listчто соответствующий тип возврата здесь.


Ты можешь использовать ? в качестве параметра типа
Даниэль Кис

Да, но это больше, чтобы напечатать, и я против ввода больше. :)
Стефан Рейх
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.