0

鉴于:

public class Base {
    public static final String FOO = "foo";
    public static void main(String[] args) {
        Base b = new Base();
        Sub s = new Sub();
        System.out.print(Base.FOO);       // <- foo
        System.out.print(Sub.FOO);        // <- bar
        System.out.print(b.FOO);          // <- foo
        System.out.print(s.FOO);          // <- bar
        System.out.print(((Base)s).FOO);  // <- foo
    } 
}

class Sub extends Base {
    public static final String FOO="bar";
  }

我的疑问是,在第 8 行和第 9 行中,我们使用引用变量来访问类的静态成员......这可能吗?因为静态成员只能通过类名访问......请纠正我哪里错了?

4

5 回答 5

5

我选D选项。

静态成员在编译时使用声明的类型而不是实际类型来解析。

这就是为什么((Base)s).FOO)Base.FOO- 即使对象是Sub.

这也将发生,并在下面得到更好的说明:

Base b = new Sub(); // valid
System.out.print(b.FOO); // foo

这里b.FOO指的是Base.FOO因为声明的类型,即使实例是一个Sub.

于 2013-09-18T14:56:09.150 回答
3

可能吗?

是的,这是可能的,尽管这不是一个好习惯。基本上,访问字段上的静态成员在编译时被解析为对字段声明类型的访问。

例如,即使以下情况也可以正常工作:

class Test {
    public static String hello = "Hello";
}

Test test = null;
System.out.println(test.hello);

print 语句不会 throw NPE,正如您在第一眼看到的那样。因为访问被有效地解析为:

Test.hello

由于声明的类型为testis Test,因此以这种方式解析访问。


现在,由于静态字段访问是在编译时使用声明的类型解析的,因此您不会看到静态方法的多态行为。就像,你不能覆盖静态方法。

于 2013-09-18T14:56:44.113 回答
1

静态成员也可以被实例访问。

IMO 这是一种不好的做法,因为它具有误导性/不交流。

事实上,您可以使用null参考,例如,

Base base = null;
System.out.println(base.FOO);
于 2013-09-18T14:56:53.963 回答
1

可以通过引用访问静态变量。但是通常你应该从你的编译器那里得到一个警告......

于 2013-09-18T14:59:45.470 回答
0

静态变量可以通过类名和引用访问。请参阅从 Java 中的对象访问静态变量

于 2013-09-18T15:01:38.230 回答