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

Это то, что мы используем:

В готовом документе мы вызываем функцию beforeunload.

$(document).ready(function(){
    $(window).bind("beforeunload", function(){ return(false); });
});

Перед отправкой или location.reload мы отвязаем переменную.

$(window).unbind('beforeunload');
formXXX.submit();

$(window).unbind("beforeunload"); 
location.reload(true);
601
задан Taryn 22 March 2017 в 16:13
поделиться

8 ответов

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

Raw -типы - это древняя история языка Java. Вначале было Коллекции , и они содержали Объектов не больше и не меньше. Каждая операция над коллекциями требовала преобразования объекта в нужный тип.

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

Более сложный интерфейс 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<MyCompareAble>
{
   int id;
   public int compareTo(MyCompareAble other)
   {return this.id - other.id;}
}

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

  • Любой объект , хранящийся в коллекции , должен быть преобразован, прежде чем его можно будет использовать
  • Использование универсальных шаблонов позволяет проверять время компиляции
  • Использование исходных типов аналогично сохранению каждого значения в виде объекта

Что делает компилятор: Универсальные шаблоны имеют обратную совместимость, они используют те же классы 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 , одна принимает MyCompareAble , а другая - Объект и передача его первому после применения.

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

58
ответ дан 22 November 2019 в 21:55
поделиться

"Сырой" тип в Java - это класс, который не является общим и имеет дело с "сырыми" объектами, а не с безопасными для типов параметрами общих типов.

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

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

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

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

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

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

16
ответ дан 22 November 2019 в 21:55
поделиться

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

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

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

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

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

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

List<String> names = new ArrayList<String>();
names.add("John");          // OK
names.add(new Integer(1));  // compile error
12
ответ дан 22 November 2019 в 21:55
поделиться

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

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

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

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

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

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

  • Не статический тип-член необработанного типа 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 - это параметризованный тип ( JLS 4.5 ). В просторечии этот тип обычно называют просто MyType для краткости, но технически он называется MyType .

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

MyType.Nested не является параметризованным типом, хотя это тип-член параметризованного типа MyType , поскольку он статический .

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 , вы могли по-прежнему использовать необработанный тип и вручную проверять каждые добавьте самостоятельно, а затем вручную приведите к String для каждого элемента из имен . Еще лучше , хотя НЕ использовать необработанный тип и позволить компилятору делать всю работу за вас , используя всю мощь дженериков Java.

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

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

См. Также


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

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

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

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

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

Обобщения в Java инвариантны. Список List не является List , поэтому следующее вызовет предупреждение компилятора:

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

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

См. Также


How's a raw тип отличается от использования в качестве параметра типа?

List , List и т. д. все List , поэтому может возникнуть соблазн просто сказать, что они просто List . Однако есть существенное различие: поскольку List определяет только add (E) , вы не можете добавить какой-либо произвольный объект в List .С другой стороны, поскольку необработанный тип List не имеет безопасности типов, вы можете добавить что угодно в список 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 names .


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

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

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

[...]

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

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

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

Рассмотрим следующий пример:

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 будет запрещено использование необработанных типов.

Эффективная версия Java 2nd Edition также может добавить следующее:

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

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

Таким образом, сырые типы НИКОГДА не должны использоваться в новом коде. Вы всегда должны использовать параметризованные типы .


Нет ли исключений?

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

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

См. Также

707
ответ дан 22 November 2019 в 21:55
поделиться

необработанный -тип - это отсутствие параметра типа при использовании универсального типа.

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

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

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

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

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.
8
ответ дан 22 November 2019 в 21:55
поделиться
 private static List<String> list = new ArrayList<String>();

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

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

Список определен для поддержки универсальных типов: открытый класс List . Это позволяет выполнять многие типобезопасные операции, которые проверяются во время компиляции.

19
ответ дан 22 November 2019 в 21:55
поделиться

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

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

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

12
ответ дан 22 November 2019 в 21:55
поделиться

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

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

private static List<String> list = new ArrayList<String>();
5
ответ дан 22 November 2019 в 21:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: