использовать varargs может потерять проверку типов во время компиляции? - PullRequest
4 голосов
/ 07 октября 2019

В книге Effective Java в пункте 42 говорится о методе varargs.

В нем говорится:

ReturnType1 suspect1(Object... args){}
<T> ReturnType2 suspect2(T... args){}

Методы с любой из этих сигнатур будутпринять любой список параметров. Любая проверка типов во время компиляции, которая была у вас до модернизации, будет потеряна.

Я запутался.

Вопрос первый: Почему модернизация / рефакторингметод к varargs может потерять проверку типов раньше в методе? В приведенных выше двух признаках метода, не является ли Object и T тип, указанный там? Каким образом мы могли бы точно потерять проверку типов? В книге объясняется, что, ссылаясь на пример, созданный автором, но я не понимаю:

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

автор сделал пример Arrays.asList(...), что до Java 1.5 , следующий код вызовет ошибку времени компиляции для проверки типа:

int[] digits = {3,1,4}
// Compiler error: asList(Object[]) in Arrays can't be applied to (int[])
System.out.println(Arrays.asList(digits));

и с java1.5 и выше , из-за введения varargs приведенный выше код подходит для компилятора. Arrays.asList(digits) объединяет все int[] в один объект, так что Arrays.asList(digits) возвращает одноэлементный массив массивов List<int[]>.

Вопрос второй: Я понимаю этот пример, это действительно пример потери проверки типов, но действие оборачивания примитивного массива int (digits) в объект выполняетсяМетод Arrays.asList(), а не использование vargars (или я здесь не прав?), Почему автор использует этот пример, чтобы сказать, что все методы с этими двумя сигнатурами могут потерять проверку типов во время компиляции? как? Какие-нибудь примеры, чтобы убедить меня?

Ответы [ 3 ]

1 голос
/ 07 октября 2019

В приведенных выше двух признаках метода не Object и T тип, указанный там?

В некотором роде, но не совсем. T будет удален во время выполнения. Простым примером является Arrays.asList(1, 2L, "3"), который упаковывает Integer, Long и String. Это приводит к тому, что тип времени компиляции T становится <Serializable & Comparable> (который является супертипом всех этих трех классов). Таким образом, в зависимости от того, что вы передаете, T "адаптируется", превращаясь в Object в самом широком случае.

.. действие оборачивания примитивного массива int (цифр) в объект выполняетсяМетод Arrays.asList (), а не использование vargars (или я здесь не прав?)

Arrays.asList() просто назначит каждому элементу входного массива список. Из-за varargs int[] {1, 2, 3} будет одним элементом (поэтому T становится int[], поскольку int не является объектом, в отличие от Integer {1, 2, 3}, где T становится Integer). Конечно, код может быть написан так, чтобы он проверял, есть ли один элемент ввода, затем проверяет, является ли он массивом, затем преобразует int[] в List<Integer>, но это сломало бы универсальные значения (int[] становится Integer внезапно), и это не единственная проблема с ним.

0 голосов
/ 08 октября 2019

Это субъект системы типов.

Можно присвоить new Object[]{1, 2L, "3"} для Object[], а также можно присвоить new Integer[]{1, 2, 3} для Object[] как Массивы ковариантны в Java . Невозможно присвоить int[] для Object[], но можно присвоить int[] для Object... args.

Метод, который принимает Object[] в качестве параметра, примет массивОбъекты любого типа, до или после Java 1.5. Но метод, который принимает Object... args в качестве параметра (только после Java 1.5), также может принимать int[].

0 голосов
/ 07 октября 2019
ReturnType1 suspect1(Object... args){}

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

<T> ReturnType2 suspect2(T... args){}

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

Чтобы знать Если вы используете vararg, вы теряете проверку типов, напишите несколько строк кода, используя vararg ипреднамеренно передайте недопустимые типы как vararg: вы увидите, если компилятор завершится с ошибкой o, если во время выполнения будет выдано исключение.

...