Каков правильный способ доступа к статическим полям в Java?

#java #class #variables #static

#java #класс #переменные #статический

Вопрос:

Я только начал изучать Java и написал класс для тестирования с использованием статических полей. Все работает нормально, но в Eclipse я вижу значок, который при наведении на который отображается как: «К статическому методу getCounter из типа CarCounter следует обращаться статическим способом«. Тогда каков правильный способ?

Вот класс:

 public class CarCounter {
    static int counter = 0;

    public CarCounter(){
        counter  ;
    }

    public static int getCounter(){
        return counter;
    }
}
  

И здесь я пытаюсь получить доступ к счетчику переменных:

 public class CarCounterTest {
    public static void main( String args[] ){
        CarCounter a = new CarCounter();
        System.out.println(a.getCounter()); //This is where the icon is marked
    }
}
  

Ответ №1:

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

 CarCounter.getCounter()
  

и не

 a.getCounter()
  

Комментарии:

1. замените need на should , поскольку обе строки кода верны, но вторая не рекомендуется

2. Это ответило на этот вопрос за меня; ваш ответ был коротким и в то же время лаконичным. Удивительно!

3. @Binyamin Sharet Я знаю, что это был более старый вопрос, но ваш комментарий помог мне в моем проекте. Спасибо!

Ответ №2:

Используйте CarCounter.getCounter() . Это дает понять, что это не имеет ничего общего с объектом, на который ссылается значение a переменной — счетчик связан с самим типом, а не с каким-либо конкретным экземпляром типа.

Вот пример того, почему это действительно важно:

 Thread t = new Thread(runnable);
t.start();
t.sleep(1000);
  

На что похоже, что делает этот код? Похоже, что он запускает новый поток, а затем каким-то образом «приостанавливает» его — переводит в спящий режим на секунду.

Фактически, это запуск нового потока и приостановка текущего потока, потому что Thread.sleep это статический метод, который всегда переводит текущий поток в спящий режим. Это не может перевести любой другой поток в спящий режим. Это намного понятнее, когда это явно:

 Thread t = new Thread(runnable);
t.start();
Thread.sleep(1000);
  

По сути, способность первого фрагмента кода компилироваться — это ошибка разработчиков языка 🙁

Комментарии:

1. разработчики c # исправили эту ошибку.

Ответ №3:

Это было бы:

 System.out.println(CarCounter.getCounter());
  

Ответ №4:

Возможно даже, хотя и крайне не рекомендуется, написать:

 Math m = null;
double d = m.sin(m.PI/4.0);
System.out.println("This should be close to 0.5 "   (d*d));
  

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

Ответ №5:

Статические элементы принадлежат классу. Следовательно, лучший способ получить к ним доступ — через класс. Итак, в вашем случае распечатка должна быть.

 System.out.println(CarCounter.getCounter());  

Это может показаться банально ненужным, но это не так.
Рассмотрим следующий код

 // VehicleCounter.java
public class VehicleCounter {
    static int counter = 0;

    public VehicleCounter(){
        counter  ;
    }

    public static int getCounter(){
        return counter;
    }
}
// CarCounter.java
public class CarCounter extends VehicleCounter {
    static int counter = 0;

    public CarCounter(){
        counter  ;
    }

    public static int getCounter(){
        return counter;
    }
}
// CarCounterTest.java
public class CarCounterTest {
    public static void main( String args[] ){
        VehicleCounter vehicle1 = new VehicleCounter();
        VehicleCounter vehicle2 = new CarCounter();
        System.out.println(vehicle1.getCounter());
        System.out.println(vehicle2.getCounter());
    }
}  

Что должен выводить приведенный выше код?

Поведение приведенного выше кода трудно определить. vehicle1 объявляется как VehicleCounter , а объект на самом деле является VehicleCounter , поэтому он должен напечатать 2 (создаются два транспортных средства).

vehicle2 объявлен как, VehicleCounter но объект является фактическим CarCounter . Что должно быть напечатано?

Я действительно не знаю, что будет напечатано, но я вижу, что это можно легко перепутать. Итак, для лучшей практики доступ к статическим элементам всегда должен осуществляться через класс, который он определил.

Гораздо проще предсказать, что будет напечатано с помощью следующего кода.

 // CarCounterTest.java
public class CarCounterTest {
    public static void main( String args[] ){
        VehicleCounter vehicle1 = new VehicleCounter();
        VehicleCounter vehicle2 = new CarCounter();
        System.out.println(VehicleCounter.getCounter());
        System.out.println(CarCounter    .getCounter());
    }
}  

Надеюсь, это объясняет.

NawaMan 😀

Ответ №6:

Доступ к статическим элементам должен осуществляться статически, т.Е. className.MemberName. Нестатический доступ разрешен, хотя (имя_объекта.имя_участника), но не рекомендуется.