При создании объекта на что указывает класс левой стороны и класс правой стороны?

Я так долго сомневался, что, наконец, спрашиваю здесь. Позвольте привести пример.

class A{
void run(){
System.out.println("hi");
}
}
class B extends A{
void jump(){
}
}

public class test{
public static void main(String[] args){
A a = new A();  //statement 1

A a1= new B(); //statement 2
B b= (B) new A(); // statement 3

a.run();
b.run();

b.jump();
}};

Теперь мое основное сомнение заключается в том, в чем разница между statement1,2,3? пожалуйста, кто-нибудь объясните мне.


person user2482323    schedule 08.09.2013    source источник
comment
Если вы попытаетесь скомпилировать это, вы увидите одно существенное отличие от утверждения 3...   -  person Oliver Charlesworth    schedule 08.09.2013
comment
А нельзя привести к Б?   -  person user2482323    schedule 08.09.2013


Ответы (4)


Теперь мое основное сомнение заключается в том, в чем разница между утверждением 1,2,3?

A a = new A(); //statement 1

Бит справа от = создает объект класса A; бит слева определяет переменную для его хранения, в данном случае это переменная типа A; = — это задание. Таким образом, создается объект класса A и сохраняется ссылка на него в переменной типа A.

A a1= new B(); //statement 2

Бит справа от = создает объект класса B; бит слева определяет переменную для его хранения, в данном случае это переменная типа A; = — это задание. Таким образом, создается объект класса B и сохраняется ссылка на него в переменной типа A. Это означает, что при доступе к объекту через эту переменную у вас есть доступ только к вещам, определенным A, даже если объект является B. Так, например, хотя B имеет метод jump, вы не можете сделать это:

a1.jump(); // Compile-time error

B b= (B) new A(); // statement 3

Произойдет сбой во время выполнения с ClassCastException, потому что вы пытаетесь сохранить A в переменной типа B. Вы не можете назначить A экземпляра B переменным. Вы можете назначать экземпляры переменным только в том случае, если они совместимы с назначением, что на практике означает:

  1. Переменная является типом класса, и объект того же типа (ваше утверждение 1)
  2. Переменная является типом класса, а тип объекта является подклассом этого типа (ваше утверждение 2)
  3. Переменная является типом интерфейса, и объект реализует этот интерфейс.
  4. Переменная представляет собой тип интерфейса, а объект реализует подинтерфейс этого интерфейса.
person T.J. Crowder    schedule 08.09.2013
comment
Спасибо за объяснение, я сомневаюсь, что указывает класс левой стороны и какой класс правой стороны? - person user2482323; 08.09.2013

Ответ TJ очень хорош и многословен, просто чтобы добавить к вашему первоначальному вопросу. Левая сторона знака «=» — это ссылка на фактический объект справа.

Думайте об этом так: левая сторона — это адрес «дома», а правая — настоящий физический «дом».

В третьем утверждении вы почти уверены, что дом 'A' is a house 'B', а затем пытаетесь разыграть его. Компилятор будет доверять вам, но управление во время выполнения может дать сбой, если ваше предположение неверно (здесь это выглядит так во время выполнения, он выдаст ClassCastEsception)

Кроме того, еще одно отличие состоит в том, что адрес в коде находится в стеке, а правая часть находится в куче памяти.

person Gyanendra Dwivedi    schedule 08.09.2013

Здесь возникают две проблемы: тип переменной или выражения и класс объекта.

У каждого объекта есть класс, который устанавливается при его создании с помощью "new" или clone(). Этот класс фиксируется на время жизни объекта.

Ссылочная переменная или выражение либо имеют значение null, либо являются указателем на некоторый объект. Тип ссылочной переменной указывается именем класса или интерфейса. Он может ссылаться на объект только в том случае, если класс объекта соответствует или расширяет, прямо или косвенно, класс или реализует интерфейс. По сути, тип переменной гарантирует, что у объекта есть соответствующие члены.

A a = new A();  //statement 1

Объявляет переменную "a" с типом A, что означает, что она может быть только нулевой или указателем на A, или объектом, класс которого расширяет A. Инициализирует ее как указатель на вновь созданный объект класса A.

A a1= new B(); //statement 2

Объявляет переменную "a1" с типом A, что означает, что она может быть только нулевой или указателем на A, или объектом, класс которого расширяет A. Инициализирует его указателем на вновь созданный B. Поскольку B расширяет A, преобразование выражение типа B для типа A разрешено.

B b= (B) new A(); // statement 3

Разница здесь в том, что A не расширяет B. Ссылка типа A может быть приведена к типу B тогда и только тогда, когда она является нулевой или указателем на объект класса B или класс, который расширяет B. Класс A не не расширять B. Компилятор примет это, потому что приведение утверждает, что "new A()" имеет значение null или ссылается на объект класса B или объект класса, расширяющий B. Он получит ClassCastException во время выполнения, потому что это утверждение ложно.

Тип ссылочной переменной или выражения определяется во время компиляции. В ходе выполнения программы он может быть нулевым или ссылаться на объекты нескольких разных классов, но только на те классы, которые соответствуют его объявленному типу.

person Patricia Shanahan    schedule 08.09.2013

Я думаю, вам нужно больше узнать о полиморфизме, то есть о способности объекта принимать множество форм. см.: полиморфизм Java, создающий объект подкласса с использованием его переменной суперкласса или: http://en.wikipedia.org/wiki/Polymorphism_(computer_science )

person dngot_    schedule 08.09.2013