Почему статическое поле должно быть доступно статическим способом?


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.Миллисекунды должны быть доступны статическим способом ? Спасибо.

3 51

3 ответа:

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

MyUnits.MILLISECONDS;

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

m.MILLISECONDS;

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

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

предположим, что у нас есть два класса, 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")

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

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 теперь неоднозначные, как компилятор не может решить, какая статическая переменная имела в виду, и сообщить об этом как об ошибке:

ошибка: ссылка на значение неоднозначна
как значение переменной в C и переменной Д матч

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

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

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

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

удачи в кодировании.


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