Почему статическое поле должно быть доступно статическим способом? - PullRequest
55 голосов
/ 13 апреля 2011
public enum MyUnits
{
    MILLSECONDS(1, "milliseconds"), SECONDS(2, "seconds"),MINUTES(3,"minutes"), HOURS(4, "hours");

    private MyUnits(int quantity, String units)
    {
        this.quantity = quantity;
        this.units = units;
    }

    private int quantity;
    private  String units;

 public String toString() 
 {
    return (quantity + " " + units);
 }

 public static void main(String[] args) 
 {
    for (MyUnits m : MyUnits.values())
    {
        System.out.println(m.MILLSECONDS);
        System.out.println(m.SECONDS);
        System.out.println(m.MINUTES);
        System.out.println(m.HOURS);
    }
 }
}

Это относится к сообщению .. не смог ответить или прокомментировать любой созданный таким образом новый.Почему мои

System.out.println(m.MILLSECONDS);

выдают предупреждения - Статическое поле MyUnits.MILLSECONDS должно быть доступно статическим способом?Спасибо.

Ответы [ 3 ]

99 голосов
/ 13 апреля 2011

Потому что, когда вы получаете доступ к статическому полю, вы должны делать это в классе (или в данном случае в enum).Как в

MyUnits.MILLISECONDS;

Не в экземпляре, как в

m.MILLISECONDS;

Редактировать Чтобы ответить на вопрос почему : в Java, когдавы объявляете что-то как static, вы говорите, что это член класса, а не объект (следовательно, почему существует только один).Поэтому нет смысла обращаться к нему на объекте, потому что этот конкретный элемент данных связан с классом.

61 голосов
/ 26 августа 2014

На самом деле есть веская причина:
Нестатический доступ не всегда работает по причинам неоднозначности .

Предположим, у нас есть два класса, A и B, последний является подклассом A, со статическими полями с одинаковыми именами:

public class A {
    public static String VALUE = "Aaa";
}

public class B extends A {
    public static String VALUE = "Bbb";
}

Прямой доступ к статической переменной:

A.VALUE (="Aaa")
B.VALUE (="Bbb")

Косвенный доступ с использованием экземпляра (выдает компилятору предупреждение о статическом доступе к VALUE):

new B().VALUE (="Bbb")

Пока все хорошо, компилятор может угадать, какую статическую переменную использовать, та, которая в суперклассе находится как-то дальше, кажется логичной.

Теперь дело доходит до сложности: интерфейсы также могут иметь статические переменные.

public interface C {
    public static String VALUE = "Ccc";
}

public interface D {
    public static String VALUE = "Ddd";
}

Давайте удалим статическую переменную из B и наблюдаем следующие ситуации:

  • B implements C, D
  • B extends A implements C
  • B extends A implements C, D
  • B extends A implements C, где A implements D
  • B extends A implements C, где C extends D
  • ...

Оператор new B().VALUE теперь неоднозначный , так как компилятор не может решить, какая статическая переменная имела в виду , и сообщит об этом как об ошибке:

ошибка: ссылка на ЗНАЧЕНИЕ неоднозначна
переменная VALUE в C и переменная VALUE в D совпадают

Именно поэтому статические переменные должны быть доступны статическим способом.

10 голосов
/ 13 апреля 2011

Потому что ... оно (MILLISECONDS) является статическим полем (скрыто в перечислении, но это то, что оно есть) ... однако оно вызывается для экземпляра данного типа(но смотрите ниже, поскольку это не действительно true 1 ).

javac это "примет", но на самом деле это должно быть MyUnits.MILLISECONDS (или(префикс в соответствующей области действия).

1 На самом деле, javac «переписывает» код в предпочтительную форму - если m окажется null, он не выдастNPE во время выполнения - он фактически никогда не вызывается для экземпляра).

Удачное кодирование.


Я не совсем понимаю, как заголовок вопроса подходит к остальным:-) Более точные и специализированные названия увеличивают вероятность того, что вопрос / ответы могут принести пользу другим программистам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...