Java - 引用变量

8
重要的是要理解,决定哪些成员可以被访问的是引用变量类型,而不是它所引用的对象类型。这句话的确切含义是什么?这是否限制于继承的概念?虚拟机如何处理它?

3
这句话出自哪里? - Maurice Perry
抱歉,但我不完全记得那个... 如果不允许我基于某些网站上发布的引用提问,请告诉我。 - Saurabh Gokhale
顺便说一句,在谷歌搜索中没有找到这个引用……除了这个页面。你可能打错了,或者你从某个未被谷歌索引的网站上得到了它!? - Stephen C
3
@Stephen: 甚至可以来自一本书! - Joachim Sauer
你可以引用网站上的内容,但是如果没有注明作者和来源,这样做就很草率、懒惰或两者兼而有之。 - Stephen C
@Joachim - 但他暗示他从一个网站得到了它... - Stephen C
6个回答

26

它意味着,假设你有:

Object x = "hello";

变量的类型是Object,但它引用的对象的类型是String。不过决定你能做什么的是变量类型,所以你不能调用

// Invalid
String y = x.toUpperCase();
编译器只知道你在调用Object上的方法,其中不包括toUpperCase。同样,重载的方法只会根据你所知道的进行解析:
public class Superclass
{
    public void foo(Object x) {}
}

public class Subclass extends Superclass
{
    public void foo(String y) {}
}
...
Subclass x = new Subclass();
Superclass y = x;

x.foo("hello"); // Calls Subclass.foo(String)
y.foo("hello"); // Calls Superclass.foo(Object)

5

例如:

Bike b = new Bike();
Bike b2 = new MountainBke();
b.speedUp();
b2.speedUp();
b2.shiftGearUp();

在上面的例子中,假设自行车没有shiftUp方法。由于JVM只知道b2是一个Bike而不是MountainBike,所以b2.shiftGearUp()这一行将无法编译。
您可以将其强制转换为山地自行车类型以使其正常工作:
((MountainBike)b2).shiftGearUp(); // This compiles and runs propperly

2

在Java中,base类类型的引用可以引用child类的对象。但是使用这样的引用,我们只能访问被继承到child类的base类成员,而不能访问child类可能添加的成员。


1

如果你有一个类Foo,其中有一个公共字段foo,以及一个类Bar extends Foo,其中有一个公共字段bar...

  • Foo myRef = new Bar();只允许访问myRef.foo,即使对象实际上是一个Bar
  • Bar myRef = new Bar();允许访问myRef.foomyRef.bar。因为引用被声明为Bar

0
public class Base
{
   public object BaseMethod()
   { 
      return new String("From Base");
   }

}

public class Child extends Base
 {
   public object BaseMethod()
   {
      return new String("From Child.BaseMethod (overridden)");
   }

   public object ChildMethod()
   {
      return new String("From Child.ChildMethod");
   }
}

public class Test
{
   public static void main(String[] args)
   {
       Base base = new Child();
       System.out.println(base.BaseMethod()); //prints "From Child.BaseMethod (overridden)"

       System.out.println(base.ChildMethod()); //Will not compile as ChildMethod as reference is of type Base, and ChildMethod is not specified.

       Child child = (Child) base; //But I can cast it.
       System.out.println(child.ChildMethod()); // This will work.
   }
}

0
“理解这一点很重要,决定可以访问哪些成员的是引用变量的类型,而不是它所引用的对象的类型。”这意味着编译器会检查引用变量的类是否存在方法和其他成员。例如,假设您有一个继承自基类Animal的Dog子类,
Animal obj=new Dog();
obj.makeSound();

在这里,编译器检查Animal类中是否声明了makeSound()方法以便进行编译。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接