我有两个类: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燃料类型:汽油
答案 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