3

I am having this doubt from so long so finally asking here. Let me give you an example.

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();
}};

Now my basic doubt is what is the difference between statement1,2,3? please someone explain me.

4

4 回答 4

13

现在我的基本疑问是语句 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

将在运行时失败, aClassCastException因为您试图将 a 存储A在 type 的变量中B。您不能将A实例分配给B变量。如果它们是assignment-compatible ,您只能将实例分配给变量,这实际上意味着:

  1. 变量是类类型,对象是相同类型(您的声明1)
  2. 变量是类类型,对象的类型是该类型的子类(您的语句 2)
  3. 变量是接口类型,对象实现该接口
  4. 变量是接口类型,对象实现该接口的接口
于 2013-09-08T10:22:18.753 回答
1

这里有两个问题令人困惑,变量或表达式的类型,以及对象的类。

每个对象都有一个类,该类在通过“new”或 clone() 创建时建立。该类在对象的生命周期内是固定的。

引用变量或表达式要么是 null,要么是指向某个对象的指针。引用变量的类型由类或接口的名称指示。只有当对象的类直接或间接匹配或扩展该类或实现接口时,它才能引用该对象。实际上,变量的类型保证了对象具有相应的成员。

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

声明一个类型为 A 的变量“a”,这意味着它只能为 null 或指向 A 的指针,或者其类扩展 A 的对象。将其初始化为指向新创建的 A 类对象的指针。

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

声明一个类型为 A 的变量“a1”,这意味着它只能为 null 或指向 A 的指针,或者其类扩展 A 的对象。用指向新创建的 B 的指针初始化它。由于 B 扩展 A,因此转换允许将 B 类型表达式转换为 A 类型。

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

这里的区别在于 A 不扩展 B。当且仅当它为 null 或指向 B 类对象的指针或扩展 B 的类时,才能将类型 A 引用强制转换为类型 B。A 类可以不扩展 B。编译器将接受这一点,因为强制转换声称“new A()”为空或引用 B 类对象或扩展 B 的类的对象。它将在运行时获得 ClassCastException,因为这种说法是错误的。

引用变量或表达式的类型在编译时确定。在程序运行的过程中,它可能为 null 或引用几个不同类的对象,但只引用适合其声明类型的类。

于 2013-09-08T10:47:32.580 回答
1

TJ 的回答非常好且冗长,只是为了添加到您原来的问题中。'=' 的左侧是对右侧实际对象的引用。

这样想,左边是“房子”的地址,而右边是实际的物理“房子”。

在第三个陈述中,你很确定房子'A' is a house 'B'然后试图铸造它。编译器会信任你,但运行时控制可能会失败,如果你的假设不正确(这里,它看起来像在运行时,它会抛出 ClassCastEsception)

此外,另一个区别是代码中的地址位于堆栈上,而右侧位于内存的堆区域。

于 2013-09-08T10:42:00.870 回答
0

我认为您需要更多地了解多态性,即对象具有多种形式的能力。请参阅: Java 多态性使用其超类变量创建子类对象 或: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)

于 2013-09-08T10:38:30.680 回答