Как мне правильно получить доступ к статическим классам-членам?
Вопрос
У меня есть два класса, и я хочу включить статический экземпляр одного класса внутри другого и получить доступ к статическим полям из второго класса через первый.
Это делается для того, чтобы у меня могли быть неидентичные экземпляры с одинаковым именем.
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 должен быть выполнен статическим способом".Может ли кто-нибудь объяснить, почему это так, и предложить "правильную" реализацию.
Я понимаю, что мог бы получить доступ к статическим экземплярам напрямую, но если у вас длинная иерархия пакетов, это становится некрасивым:
assertEquals(net.FooCorp.divisions.A.package.Foo.bar, 1);
assertEquals(net.FooCorp.divisions.B.package.Foo.bar, 2);
Решение
Я согласен с другими, что вы, вероятно, думаете об этом неправильно.Учитывая это, это может сработать для вас, если вы обращаетесь только к статическим участникам:
public class A {
public static class Foo extends package1.Foo {}
}
public class B {
public static class Foo extends package2.Foo {}
}
Другие советы
Вы должны использовать:
Foo.bar
И не:
A.foo.bar
Вот что означает это предупреждение.
Причина в том, что bar
не является членом экземпляр из Foo
.Скорее, bar
является глобальным в зависимости от класса Foo
.Компилятор хочет, чтобы вы ссылались на него глобально, а не притворялись, что это член экземпляра.
Нет смысла помещать эти две статические переменные в эти классы to, если вам нужен доступ только к статическим членам.Компилятор ожидает, что вы получите к ним доступ через префиксы имен классов, такие как:
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 .Поэтому лучше ссылаться на него по имени класса, поскольку, если вы попытаетесь воспользоваться преимуществами наследования, вы прострелите себе ногу.