如何在我的代码中正确使用静态变量?

时间:2018-12-28 16:21:50

标签: java member static-members

我有两个类: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条记录。我希望每辆车都有一个唯一的ID,但是运行程序时结果总是每辆车10。我要使宝马为1,福特为2,大众为3,依此类推。

一点输出:

汽车ID:10制造商:bmw变速箱:机械师PS:200燃料类型:柴油

汽车ID:10制造商:ford变速箱:自动PS:150燃料类型:汽油

汽车ID:10制造商:vw变速箱:机械师PS:120燃料类型:汽油

汽车ID:10制造商:audi变速箱:机械师PS:100燃料类型:汽油

5 个答案:

答案 0 :(得分:3)

您应将carID设为非静态,并创建一个单独的静态变量以用作自动增量,例如nextCarID。然后,您可以通过carID来填充this.carID = nextCarID++;

答案 1 :(得分:3)

输入汽车ID static意味着所有汽车将共享ID。取而代之的是,您可以有一个具有ID的实例成员,并为下一个ID保留一个静态计数器。例如:

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
    }
}

答案 2 :(得分:2)

为了绝对安全,您需要使用同步。 @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成员获得唯一的值。

答案 3 :(得分:1)

这是因为您的Car类中的静态字段carId的值对于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
}

答案 4 :(得分:1)

虽然@Mureinik的答案似乎行得通,但它在技术上存在缺陷,并且会成为一种坏习惯。它不仅允许可能重复的汽车ID,而且可能很难找到这类错误。

在克里斯托弗·舒尔茨(Christopher Schultz)的答案中,确保CarId正确多线程行为的另一件事是添加“ volatile”以确保Java虚拟机将其正确视为共享变量,并确保对其价值的一致看法每个线程。

有关Java字段修饰符的详细信息,请参见:Java Language Specification - Field Modifiers