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

时间:2020-03-05 18:59:45  来源:igfitidea点击:

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

这样一来,我可以拥有名称相同的不同实例。

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);

这行得通,但是我收到一条警告"以静态方式访问静态字段Foo.bar shoudl"。
有人可以解释为什么会这样,并提供"正确"的实现。

我意识到我可以直接访问静态实例,但是如果包层次结构很长,那就太丑了:

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

解决方案

回答

我们应该使用:

Foo.bar

并不是:

A.foo.bar

这就是警告的意思。

原因是" bar"不是" Foo"实例的成员。相反," bar"是全局类,在" Foo"类上。编译器希望我们全局引用它,而不是假装它是实例的成员。

回答

只要我们只需要访问静态成员,就没有必要将这两个静态变量放入类中。
编译器希望我们通过类似的类名前缀来访问它们:

package1.Foo.bar
package2.Foo.bar

回答

在以下位置创建对象后:

public static package1.Foo foo;

它不是以静态方式访问的。我们将必须使用类名,当然还要使用完整的包名来寻址该类,因为它们在不同的包上具有相同的名称

回答

确实,Foo实例可以访问Foo的静态字段,但是请考虑"静态"一词。至少在这种情况下,它表示"静态绑定"。由于A.foo的类型为Foo,因此" A.foo.bar"不会向对象询问" bar",因此它将直接转到该类。这意味着,即使子类具有名为" bar"的静态字段,并且foo是该子类的实例,也将获取Foo.bar,而不是FooSubclass.bar。因此,最好通过类名来引用它,因为如果我们尝试利用继承,我们将一头雾水。

回答

我同意其他人的看法,我们可能正在考虑这种错误的方式。这样一来,如果我们仅访问静态成员,则可能对我们有用:

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