Правила для преобразования (что происходит, когда значение выражения присваивается переменной) записаны в section 5.2 of the Java Language Specification. В частности, это всегда законно присвоить ссылочный тип к шире контрольной переменной:
расширяющейся ссылочное преобразование существует от любого ссылочного типа S к любому ссылочного типа T, при условии S является подтипом (п. 4.10) от T.
В вашем случае, поскольку test
имеет ссылочный тип Test1
, это законно присвоить все, что типа Test1
или любого подтипа Test1
к test
. Однако, поскольку test1
имеет тип Test2
, нецелесообразно присваивать ему выражение типа Test1
, поскольку Test1
не является подтипом Test2
. В частности, выражение test
имеет тип Test1
и Test1
не является подтипом Test2
.
Обратите внимание, что это проверка времени компиляции и не зависит от типа фактического значения, которое test
будет иметь во время выполнения. Если вы уверены, что выражение на самом деле из узкого типа, вы можете использовать бросок:
test1 = (Test2) test;
Однако, это поднимет ClassCastException
во время выполнения, если фактическое значение test
не типа Test2
(или подтип). Поэтому, когда вы выполняете такие отбрасывания, вы теряете некоторые преимущества проверки типа компиляции. Обычно используется оператор instanceof
, чтобы проверить, что приведение будет успешным. Однако, если вы так программируете, это «запах кода»: указание на то, что ваш дизайн кода может быть каким-то образом недостаточным.
Подобное происходит с примитивными значениями:
int x = 1;
byte y = 2;
x = y; // okay
y = x; // ERROR -- requires a cast to narrow the type
y = (byte) x; // okay
В отличие от ссылочных типов, слепки примитивных типов никогда не будет бросать ClassCastException
.
Как может быть строка _false_? Что вы имеете в виду? –
Под «истинным» и «ложным» вы действительно подразумеваете «компилирует» и «не компилируется»? –
'Test1 (1,2);' Test1 не имеет этого конструктора, как это можно даже скомпилировать? – csmckelvey