【问题标题】:what is the importance of reference variable type?引用变量类型的重要性是什么?
【发布时间】:2014-09-23 16:57:41
【问题描述】:
Dog dogObj = new Dog();

是的,我知道我们必须为引用变量提供合适的类型,以便它可以为对象的位置地址或我们放入其中的任何内容保留一个位置。

引用变量存储位于寄存器堆中的真实对象的8字节地址(数字)。所以它的工作就是保存那个位置的地址。那为什么它需要一个类型呢?给它一个类型后,这 8 个字节会发生什么变化。即使它没有类型,它仍然可以将 8 字节数据指向该位置。

这背后的细节是什么?

【问题讨论】:

    标签: java


    【解决方案1】:

    如果您想要一个变量可以只保存任何参考值,这很容易做到:

    Object dogObj = new Dog();
    

    但是,如果您随后尝试调用:

    dogObj.bark();
    

    ...你不应该对编译器不知道你在说什么感到惊讶。编译器使用变量的声明类型来知道如何使用它……就这么简单。

    【讨论】:

    • 引用可以指向任何实现或继承此引用类型的实际对象。简单的例子是当你做List<String> list = new ArrayList<String>();
    • 谢谢@JonSkeet。你的意思是为了知道如何使用它,对象本身并不重要。我认为引用变量的工作只是指向对象的真实位置而不是更多。
    • @Skeletor:除非变量具有特定类型,否则编译器如何知道其中可能存储了什么样的引用?你了解编译时和执行时的区别吗?
    • 是的,我知道编译时和执行时的区别。但我不明白的是为什么编译器需要知道其中可能存储了什么样的引用。它不只是一个地址号码吗?引用只是一个可以是任何数字的数字。
    • @Skeletor:但是如果你有一个声明为Dog 类型的变量,VM 将保证值 不是 只是任何东西——它要么是空引用,或对与Dog 兼容的类型的引用...所以调用bark() 是安全的。如果您只有声明为Object 类型的变量,它可能是对非Dog 对象的引用,因此您不能调用bark()。变量类型提供有关该数字的含义的编译时信息。
    【解决方案2】:

    阅读:http://www.javaranch.com/campfire/StoryCups.jsp

    然后阅读它的后续:http://www.javaranch.com/campfire/StoryPassBy.jsp

    但基本上,你需要给它一个类型,以便编译器知道它是那个类型。请注意,您也可以这样做,这基本上就是您所说的:

    Object dogObj = new Dog();
    

    但是你只能在该变量上使用 Object 中定义的方法,因为编译器无法保证某个 Object 是否是更具体的类型。

    编辑:假设您有两个类,Dog 和 Cat。 Dog 有 bark() 方法,Cat 有 meow() 方法。

    你可以这样做,因为正如你所说,参考就是参考:

    Object dog = new Dog();
    

    但是,你将无法做到这一点:

    dog.bark();
    

    即使 Dog 类有一个 bark() 方法,并且 dog 变量是 Dog 的一个实例,编译器并不知道这一点。事实上,编译器无法知道什么。毕竟,你也可以这样做:

    Object dog = new Dog();
    dog = new Cat();
    dog.bark(); //good thing this is a compiler error!
    

    您可能会想,为什么编译器无法解决这个问题?原因是这样的代码可能会发生:

    Object dog = new Dog();
    if(Math.random() < .5){
       dog = new Cat();
    }
    //what type is dog now??
    

    所以编译器只能保证一个Object就是变量的类型。这就是为什么你需要给每个变量一个类型。

    请注意,您还可以强制转换变量以明确告诉编译器某物是什么类型:

    Object dog = new Dog();
    dog = new Cat();
    ((Cat)dog).meow(); //this will now work, since the compiler knows dog is a Cat!
    

    但要小心,因为如果你错了,你会得到一个运行时错误:

    Object dog = new Dog();
    dog = new Cat();
    ((Dog)dog).bark(); //this won't work, since dog is actually a Cat!
    

    我强烈建议将您自己的运行与这些示例类似的代码的小测试程序放在一起,这样您就可以更好地了解正在发生的事情。

    【讨论】:

    • 感谢@KevinWorkman 的链接和解释。书头首先java告诉了同样的事情。但是你说:“你需要给它一个类型,以便编译器知道它是什么类型”但是编译器没有从对象本身获取这个信息。
    • @Skeletor 不。编译器只知道你告诉它什么。如果将引用保存为 Object 变量,那么编译器唯一知道的就是该值是 某种 Object。如果不将 Dog 类中定义的任何方法强制转换为 Dog 变量,您将无法访问它,因为稍后您可能会将 Cat 实例存储在同一个 Object 变量中。
    • @Skeletor 查看我编辑的答案以获得更详细的解释。
    • 好的@KevinWorkman 我想我明白了(我应用了你的例子)。那么我们可以说,引用变量不仅保存了指向对象的地址,它还保存了我们声明对象类型时有关对象内容的信息。我的意思是对象可以做什么的信息。对吗?
    【解决方案3】:

    声明不仅仅是内存分配。不使用类型的 OOP 不是 OOP,您不是在操作原始字节,而是在操作具有精确角色和精确逻辑的对象。这就是类的用途。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-16
      • 1970-01-01
      • 2011-01-03
      • 2016-09-21
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      相关资源
      最近更新 更多