У меня есть два класса, и я хочу включить статический экземпляр одного класса в другой и получить доступ к статическим полям из второго класса через первый.
Это значит, что у меня могут быть неидентичные экземпляры с одним и тем же именем.
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);




Вам следует использовать:
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 {}
}
Спасибо, это способ сделать это, даже если это не «java-способ». Я знал, что это возможно, потому что я мог создать статический внутренний класс, и он не выдал бы ошибок, но это было бы кошмаром обслуживания, и, следовательно, было бы справедливо обескуражено.
Для его варианта использования потребуется
import package1.Foo; import package2.Foo;, что является незаконным, поскольку делает Foo неоднозначным.