2015-02-03 1 views
-2
public class Test1 { 

    int a; 
    int b; 

} 

public class Test2 extends Test1 { 

    public int c; 

    Test2(int a,int b,int c){ 

     this.a=a; 
     this.b=b;  
     this.c=c;} 
} 


public class Driver { 

    public static void main(String[] args) { 

     Test2 test1 = new Test2(3,4,5); 
     Test1 test = new Test1(); 

     test=test1; //This line is true 
     test1=test; //This line is false 

    } 

} 

Я не мог понять, хотя я посмотрел на пример в книге. Как это возможно? Почему? Ошибка компиляции в строке «test1 = test»? Может кто-нибудь объяснить это?Ссылки на Java Наследование Примеры

+2

Как может быть строка _false_? Что вы имеете в виду? –

+4

Под «истинным» и «ложным» вы действительно подразумеваете «компилирует» и «не компилируется»? –

+1

'Test1 (1,2);' Test1 не имеет этого конструктора, как это можно даже скомпилировать? – csmckelvey

ответ

2

Правила для преобразования (что происходит, когда значение выражения присваивается переменной) записаны в 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.