如何正确访问静态成员类?

4

我有两个类,想在其中一个类内包含另一个类的静态实例,并通过第一个类访问第二个类的静态字段。

这样我可以拥有名称相同但非相同的实例。

Class A 
{
    public static package1.Foo foo;
}

Class B 
{
    public static package2.Foo foo;
}


//package1
Foo 
{
    public final static int bar = 1;
}

// package2
Foo
{
    public final static int bar = 2;
}

// usage
assertEquals(A.foo.bar, 1);
assertEquals(B.foo.bar, 2);

这种写法是能用,但会出现一个警告:"The static field Foo.bar should be accessed in a static way"。有人能解释一下为什么会有这个警告,并提供一种"正确"的实现方法吗?

我知道可以直接访问静态实例,但如果包层次很深,那就很麻烦:

assertEquals(net.FooCorp.divisions.A.package.Foo.bar, 1);
assertEquals(net.FooCorp.divisions.B.package.Foo.bar, 2);
5个回答

10

您应该使用:

Foo.bar

而不是:

A.foo.bar

这就是警告的含义。

原因是bar不是Foo类实例的成员,而是在Foo类上全局存在。编译器希望您将其作为全局引用,而不是假装它是实例的成员。


他的使用情况需要 import package1.Foo; import package2.Foo;,这是非法的,因为它使得 Foo 不明确。 - erickson

2

一旦您在以下位置创建了对象:

public static package1.Foo foo;

这里涉及到的是非静态方式访问,你需要使用类名和完整的包名来引用该类,因为它们在不同的包中具有相同的名称。


2
只要您只需要访问静态成员,就没有必要将这两个静态变量放在这两个类中。编译器希望您通过类名前缀来访问它们,例如:
package1.Foo.bar
package2.Foo.bar

1

我同意其他人的看法,你可能正在错误的思考这个问题。既然这个问题已经解决了,如果你只是访问静态成员,这个方法可能适用于你:

public class A {
    public static class Foo extends package1.Foo {}
}
public class B {
    public static class Foo extends package2.Foo {}
}

谢谢,这就是正确的方法,即使它不是"Java 的方式"。我知道这是可能的,因为我可以创建静态内部类,不会出现错误,但那会成为一个维护噩梦,因此是被 rightly discouraged. - fijiaaron

0

Foo实例确实可以访问Foo的静态字段,但是请考虑一下“static”这个词。至少在这种情况下,它意味着“静态绑定”。由于A.foo的类型是Foo,因此“A.foo.bar”不会要求对象提供“bar”,而是直接转到类。这意味着即使子类有一个名为“bar”的静态字段,并且foo是该子类的实例,它也将获得Foo.bar,而不是FooSubclass.bar。因此,最好通过类名引用它,因为如果您尝试利用继承,您将自食其果。


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