Почему назначения массивов несовместимы, даже если их типы данных? - PullRequest
0 голосов
/ 07 июня 2018
byte b =10;   
int a = b;   // Primitive data type widening
             // Works perfectly fine

приведенный выше код не выдаст ошибки / предупреждения.Но почему то же самое не применимо для приведенного ниже кода?

byte[] b = new byte[10];
int[] i1 = b;             //Cannot convert from byte[] to int[]
int[] i2 = new byte[10];  //Cannot convert from byte[] to int[]

Мой вопрос таков: поскольку int может содержать любые байтовые значения, почему это не относится к массивам?

они оба держат адреса в конце концов.И это было бы upcasting , если бы это было возможно для переменных ref.

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Спецификация языка определяет подтипы между типами массивов в Sec 4.10.3 :

Следующие правила определяют прямое отношение супертипа между типами массивов:

  • Если S и T оба являются ссылочными типами, то S[] >1 T[] iff S >1 T.

  • Object >1 Object[]

  • Cloneable >1 Object[]

  • java.io.Serializable >1 Object[]

  • Если P является примитивным типом, то:

    • Object >1 P[]

    • Cloneable >1 P[]

    • java.io.Serializable >1 P[]

Последние маркеры («Если P является примитивным типом ...») показывают, что язык не определяет никакой связи между массивами различных примитивных типов.Единственные допустимые назначения:

byte[] bs = new byte[10];

byte[] bs2 = bs;
Object obj = bs;
Cloneable cl = bs;
Serializable ser = bs;

Это не дает ответа относительно почему это так;Вы должны спросить языковых дизайнеров.Однако простые примеры, подобные показанным Eran , демонстрируют, почему было бы небезопасно делать так, как предлагает OP.

Следует отметить, что первая строка - которая разрешает присваивание, например

Object[] obj = new String[10];
obj[0] = new Object();  // ArrayStoreException!

- ошибка проектирования: ковариантность массивов делает их небезопасными.Это одна из причин, по которой я настоятельно предпочитаю обобщенные элементы массивам, поскольку обобщенные элементы инвариантны и поэтому предотвращают такие назначения.

0 голосов
/ 07 июня 2018

Массив, созданный new byte[10], может содержать 10 byte значений.Если бы вы смогли присвоить его переменной типа int[], компилятор предположил бы (ошибочно), что ваш массив byte s может содержать 10 int значений.

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

byte[] b = new byte[10];
b[0] = 10000; // too large for byte

и следующий действительный код:

int[] i2 = new int[10];
i2[0] = 10000;

Если бы int[] i2 = new byte[10]; был действительным, компилятор позволил бы вам сохранить intв переменной типа byte.

...