Как правильно использовать статическую переменную в моем коде? - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть два класса: Car и LearnArrayList.Автомобиль инкапсулированного класса, имеющий такие свойства, как: производитель, коробка передач, ps, fuelType, статический carID (ПРОБЛЕМА С ЭТОЙ ПЕРЕМЕННОЙ).Я вставил в конструктор Car утверждение, что увеличивает carID на 1 (carID ++).Я создал такой код для изучения arrayList:

public class LearnArrayList implements FutureFunctionality {

    public static void main(String[] args) {

        LearnArrayList learn = new LearnArrayList();
        learn.createObjects();
        learn.getInfo();
    }

    List<Car> listOfCars = new ArrayList();

    public void createObjects() {

        Car bmw = new Car("bmw", "mechanic", 200, "diesel");
        Car ford = new Car("ford", "automatic", 150, "petrol");
        Car vw = new Car("vw", "mechanic", 120, "petrol");
        Car audi = new Car("audi", "mechanic", 100, "petrol");
        Car mercedes = new Car("mercedes", "mechanic", 200, "diesel");
        Car opel = new Car("opel", "automatic", 105, "petrol");
        Car toyota = new Car("toyota", "mechanic", 103, "petrol");
        Car renault = new Car("renault", "automatic", 100, "diesel");
        Car dacia = new Car("dacia", "mechanic", 250, "petrol");
        Car lada = new Car("lada", "mechanic", 80, "petrol");

        Car[] cars = { bmw, ford, vw, audi, mercedes, opel, toyota, renault, dacia, lada };

        for (int i = 0; i < cars.length; i++) {
            addToArrayList(cars[i]);
        }
    }

    @Override
    public void addToArrayList(Car car) {
        listOfCars.add(car);
    }

    @Override
    public void getInfo() {
        for (int i = 0; i < listOfCars.size(); i++) {
            System.out.println(listOfCars.get(i).toString());
        }
    }
}

Мой вывод должен быть 10 записей.Я хочу иметь уникальный идентификатор для каждой машины, но результат, когда я запускаю программу, всегда равен 10 для каждой машины.Я хочу сделать так, чтобы bmw был 1, ford - 2, vw - 3 и т. Д.

Немного о выходе:

Идентификатор машины: 10 Производитель: bmw GearBox: механик PS: 200 FuelType: дизель

Идентификатор автомобиля: 10 Производитель: ford GearBox: автомат PS: 150 FuelType: бензин

Идентификатор автомобиля: 10 Производитель: vw GearBox: механик PS: 120 FuelType: бензин

ID автомобиля: 10 Производитель: audi GearBox: механик PS: 100 Тип топлива: бензин

Ответы [ 5 ]

0 голосов
/ 28 декабря 2018

Хотя ответ @ Mureinik может сработать, он технически ошибочен и может стать вредной привычкой.Мало того, что он допускает потенциально дублирующиеся идентификаторы автомобилей, но такие ошибки могут быть трудно найти.

Еще одна вещь, обеспечивающая правильное многопоточное поведение CarId в ответе Кристофера Шульца, заключается в добавлении«volatile», чтобы гарантировать, что виртуальная машина Java правильно обрабатывает ее как общую переменную и обеспечивает согласованное представление ее значения для каждого потока.

Подробную информацию о модификаторах полей Java можно найти здесь: Язык JavaСпецификация - полевые модификаторы

0 голосов
/ 28 декабря 2018

Чтобы быть абсолютно безопасным, вам нужно использовать синхронизацию.Ответ @ Mureinik, вероятно, будет работать большую часть времени, но есть крайние случаи, когда многопоточный доступ может быть не синхронизирован.В вашем «автомобильном» примере это не имеет значения.При управлении автомобилем с самостоятельным вождением проблема может быть более серьезной.

Самая безопасная реализация вашего класса Car выглядит следующим образом:

public class Car {
    private static CarId = 0;
    private static synchronized int nextCarId() { return CarId++ };

    private int id;
    public Car() {
      this.id = nextCarId();
    }
}

Это гарантирует, что все потоки всегда видятправильное значение для Car.CarId, и каждый экземпляр Car получает уникальное значение для своего id члена.

0 голосов
/ 28 декабря 2018

Создание идентификатора автомобиля static означает, что все автомобили будут иметь идентификаторы.Вместо этого вы можете иметь экземпляр экземпляра с идентификатором и хранить статический счетчик для следующего идентификатора.Например:

public class Car {
    private static int nextId = 1;
    private int id;
    // Other data members...

    public Car(/* arguemnts... */) {
        id = nextId;
        ++nextId;
        // Handle the other arguments and store them in data member
    }
}
0 голосов
/ 28 декабря 2018

Это потому, что значение статического поля carId внутри вашего класса Car будет одинаковым для каждого класса Car.Вы можете создать статический idCounter, затем увеличить его и передать это значение для обычного поля carId.Но этот подход не является потокобезопасным.

  public class Car{
        private static long m_idCounter = 0; // initial value
        private long m_carId;
         // .. other fields

   public Car () {
        this.m_carId = m_idCounter; // new id simulation
        this.m_idCounter+=1; // id for next car instance. Same value for all instances of Car class.
        //... do other stuffs
   }

  //... stuffs
}
0 голосов
/ 28 декабря 2018

Вы должны сделать carID нестатичным и создать отдельную статическую переменную, которая будет служить автоматическим приращением, как, скажем, nextCarID.Затем вы можете заполнить carID через this.carID = nextCarID++;.

...