为什么在用作其他对象类型时必须转换对象类型的引用变量

时间:2012-03-23 15:53:59

标签: java object reference

虽然Java中的所有类都是Object类的子类,但与其他对象类型不同,但是如果没有强制转换,则不能将Object类型的引用变量赋值给任何其他引用类型。

例如:

public class Inheritance {

    public static class Animal {        
        public void Scream() {
            System.out.println("I'm an animal");
        }       
    }

    public  static class Mammal extends Animal{
        public void Scream(){
            System.out.println("I'm a mammal");
        }       
    }

    public  static class Tiger extends Mammal{
        public void Scream(){
            System.out.println("I'm a tiger");
        }       
    }

    public static void main (String[] args){

        Animal tiger = new Tiger();
        tiger.Scream(); //true

        Object tiger = new Tiger();
        tiger.Scream(); //false

        Object tiger = new Tiger();
        ((Animal) tiger).Scream(); //true

    }

}

4 个答案:

答案 0 :(得分:5)

你想知道为什么我们使用显式类型转换。 这都是关于继承 -

让我清楚这一点 - 假设我们有两个类 A类 B类 B类 A类的子类。这意味着 B类具有 A类的所有功能,这意味着 B类可以执行 A类所能做的任何事情做。 所以,如果

 A a = new B();

非常好,因为 B级可以做 A级所能做的事情。 这里引用变量 a 是类A的类型,来自A类的所有方法都是invokable.Now B 的对象(new B();)具有所有 A类的功能(作为继承),因此 A类的所有方法都可以调用。

如果我们改变这样的条件 - >

      B b =new A();

不可能,因为可能 B类实现其自身的功能(方法和变量),这些功能不在 A类中。但是这里引用变量的类型为 B B类的所有功能都是可调用的,但实际对象的类型为 A ,所以错误会发生。

同样的情况是类对象。所有其他类自动继承对象类。

所以当任何具有Class Object类型的引用变量的对象需要显式Cast时,因为这不确定该对象包含的或多或少的功能。

答案 1 :(得分:2)

一旦您将tiger分配给Object引用,编译器就不再知道它实际上是Tiger。它只知道tiger对象是Object - 它可能是StringIntegerFruitcakeAnimal

这正是它应该如何运作的。

答案 2 :(得分:2)

由于Scream()未被声明为Object的公共方法,因此您无法在Object类型的变量上调用它。编译器只知道 static 类型的变量(引用),因此它无法告诉或验证此引用是否会在运行时指向类型为Tiger的对象(这将是是动态类型)。这就是编译错误的原因。

您可能会说编译器在上述情况下验证动态类型是微不足道的,这或多或少是正确的。然而,在现实生活中,它通常不那么简单。考虑

Factory factory = new SomeFactory();
Object obj = factory.getProduct(param);
// What is obj's dynamic type?

编译器理论上可以检测到factory的动态类型是SomeFactory。然后它应该做的是静态分析SomeFactory.getProduct()中的代码以检测返回的产品的类型。当然,getProduct可能会根据其参数返回不同类型的实际产品。因此编译器需要在调用时检测param的可能值...这可能来自任何数量的源,例如用户输入,配置文件,DB ......但即使这是可以克服的,具体的产品类也可以在运行时由类加载器动态加载,从jar文件中甚至可能在编译时不可用。所以编译器甚至可能不知道这个特定类的存在,更不用说它的公共接口了。

答案 3 :(得分:2)

鉴于声明:Object o = new Tiger();

变量的类型(Object)控制您可用的交互(方法),而值的类型(Tiger)控制为给定交互执行的行为。

通过在此示例中使用Tiger实例的Object引用,您说要使用Tiger的实例作为Object。好吧,一个对象没有方法Scream()所以它不会给你那个选项。如果您希望能够Scream(),请将其用作实际知道如何Scream()AnimalMammal

的类型 顺便说一句,方法应该以小写

开头