2017-02-16 17 views
0

Рассмотрим следующий код:Явная литья и переназначение

class A{} 

class B extends A{ 

public static void main(String args[]){ 
    A exampleA = new A(); 
    B exampleB = new B(); 
    exampleB = exampleA; // compile error} 

Я понимаю, почему это приводит к ошибке, потому что вам нужно явное приведение. Тем не менее, я не понимаю, почему я получаю ошибку компиляции с помощью следующего кода:

class A{} 

class B extends A{ 

public static void main(String args[]){ 
    A exampleA = new A(); 
    B exampleB = new B(); 
    exampleA = exampleB; 
    exampleB = exampleA; // compile error 

С моей точки зрения, указатель exampleA теперь указывает на тот же объект, как это делает exampleB, который является объектом класса В Кроме того, из-за переназначения примера указателя A я интерпретирую последнюю строку кода как пример B = exampleB; Компилятор не согласен, и я не могу думать как компилятор. Может кто-нибудь сказать мне, почему я получаю сообщение об ошибке?

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

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

Обратите внимание, что я знаю, как решить второй блок кода, который просто выполняет явное литье.

+3

«потому что вам нужно явное приведение» Вы бы получить 'ClassCastException' во время выполнения, если вы сделали это: все' 'B's являются A's, но не все' 'A's являются B' s. –

+3

Компилятор Java не отслеживает значения через ваш код: он просто берет их по номиналу. Вы просто не можете назначить 'A'' B', не отбрасывая его; и это может завершиться неудачно во время выполнения, если на самом деле это не 'B'. –

+0

Да, я забыл об этом, я бы получил ClassCastException во время выполнения, потому что во время инициализации они не связаны друг с другом. Тем не менее, это не отвечает на мой вопрос, почему я получаю ошибку компиляции. Почему компилятор не видит этого? @AndyTurner: ваш второй комментарий частично ответил на мой вопрос. Спасибо. Как узнать, как изолировать логическое отслеживание от того, что вы называете временем лица? Любые книги, которые помогают мне в этом? – AJavaStudent

ответ

1

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

Down cast by put exampleB = (B) exampleA;.

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

Кроме того, в Java нет указателей. Ссылки похожи, но не совпадают.

+0

На самом деле ссылки на Java - это точно указатели. –

-2

Вы имеете право об объектах - они имеют один и тот же тип.

Но! указатели по-прежнему имеют разные типы.

Итак, вот почему эта ошибка.

0

Вы, кажется, хотите узнать о компиляторе, поэтому я поместил бы столько, что мог, как могу. Компилятор java в java гораздо более доверчив, чем некоторые считают. Это отличный случай, потому что java позволяет вам создавать механизмы искусственного литья, хотя в большинстве случаев с большими трудностями. Таким образом, компилятор делает шаг назад и надеется, что вы знаете, что делаете. Разумеется, Runtime - это то, где все идет не так, как в фантастическом стиле, и видит в действии, что нет, этот прилив невозможен. В этом конкретном случае класс A, очевидно, не может подавить, чтобы стать примером класса B. Однако переключите последние две строки вокруг, и я считаю, что вы обнаружите, что ошибок не происходит. Это связано с тем, что класс B, скорее всего, может стать примером класса A, и когда вы установите eB как пример класса A и установите eA равным B, вы найдете оба примера в качестве примеров класса A.

class A{} 

class B extends A{} 

public static void main(String args[]){ 
    A exampleA = new A(); 
    B exampleB = new B(); 
    exampleB = exampleA; 
    exampleA = exampleB; // compile error should be fixed 
} 

EDIT: Я понял, что был неправ. Подробнее см. Комментарии ниже. Вот моя исправленная версия.

public static void main(String[] args) { 
    A eA = new A(); 
    B eB = new B(); 
    A newAfromB = eB; 
    eA = newAfromB; 
} 
+0

Привет, Сирис, спасибо за ваш ответ. Можете ли вы показать мне в коде, что вы имеете в виду: однако, переключите последние две строки вокруг, и я считаю, что вы обнаружите, что ошибок не происходит. Это связано с тем, что класс B, безусловно, может стать примером класса A, а когда вы установите eB как пример класса A и установите eA равным B, вы найдете оба примера в качестве примеров класса A. Thank вы! – AJavaStudent

+0

О, извините! Я отредактировал его, но я думаю, что он не держался. Я попробую еще раз. Дайте минуту. – Siris

+0

Подождите минуту. Прости. Я забыл - вам нужно новое объявление для повышения. Я был неправ. – Siris