如果我在 getter 内初始化会出现任何问题吗?
我在旅游领域工作。例如,创建了 Main
类。这些 bean 在 web-java-project 中使用。下面的代码按预期工作正常。我仍然怀疑将来是否可能发生任何未知问题(Vechiles
类在应用程序中广泛使用)。
Singleton
应该通过 constructor
获得,但在本例中我是通过 getter
实现的。 setter
也保持原样(所以我不确定它是否可以称为单例。
汽车
public class Car {
private int wheelCount;
public int getWheelCount() {
return wheelCount;
}
public void setWheelCount(int wheelCount) {
this.wheelCount = wheelCount;
}
}
车辆
public class Vehicles {
private Car car;
public Car getCar() {
if(car == null){
Car newCar = new Car();
this.car = newCar;
return newCar;
}
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
< strong>主类
public class Foo {
public static void main(String[] args) {
Vehicles vehicles = new Vehicles();
Car car1 = vehicles.getCar();
car1.setWheelCount(3);
System.out.println(vehicles.getCar().getWheelCount());
Car anotherCar = vehicles.getCar();
vehicles.setCar(anotherCar);
vehicles.getCar().setWheelCount(4);
System.out.println(vehicles.getCar().getWheelCount());
Car car_withNew = new Car();
vehicles.setCar(car_withNew);
System.out.println(vehicles.getCar().getWheelCount());
}
}
输出:(符合预期)
3
4
0
要求:vehicles.getCar().setWheelCount(x);
应该是可能的。否则,每次我都需要检查 Car
是否存在。如果不存在,则使用 new
关键字创建一个,然后使用 setter
设置它。
应该像这样初始化内部 getter 吗?
我发现的一个问题:
注意:通常车辆
可能包含汽车
,也可能不包含。但在这种情况下,Vehicles
将始终包含一个 Car(当调用 getter 时)!!!因此,在这种情况下,对于给定的汽车模型,没有选项可以检查它是否为 NULL(汽车是否存在)。它永远不会是NULL。
还有其他问题吗?
I work in travel domain. The Main
class is created for example. The beans are used in web-java-project. The code below is working fine as expected. Still I doubt if there's any unknown problem which may happen in future (the Vechiles
class is used widely in the application).
Singleton
should be attained through constructor
but in this case I did it through getter
. Also the setter
is kept as it is (so I am not sure it can be called as Singleton or not.
Car
public class Car {
private int wheelCount;
public int getWheelCount() {
return wheelCount;
}
public void setWheelCount(int wheelCount) {
this.wheelCount = wheelCount;
}
}
Vehicles
public class Vehicles {
private Car car;
public Car getCar() {
if(car == null){
Car newCar = new Car();
this.car = newCar;
return newCar;
}
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
Main class
public class Foo {
public static void main(String[] args) {
Vehicles vehicles = new Vehicles();
Car car1 = vehicles.getCar();
car1.setWheelCount(3);
System.out.println(vehicles.getCar().getWheelCount());
Car anotherCar = vehicles.getCar();
vehicles.setCar(anotherCar);
vehicles.getCar().setWheelCount(4);
System.out.println(vehicles.getCar().getWheelCount());
Car car_withNew = new Car();
vehicles.setCar(car_withNew);
System.out.println(vehicles.getCar().getWheelCount());
}
}
Output: (comes as expected)
3
4
0
Requirement:vehicles.getCar().setWheelCount(x);
should be possible. Otherwise, each time, I need to check, whether a Car
exists or not. If does not exists, create one with new
keyword and then set it with setter
.
Should initialize inside getter like this?
One problem I found :
Note: Usually The Vehicles
might contain a Car
or might not. But in this case, the Vehicles
will always contain a Car (when getter is called) !!! So, in that case, with the given Car model, there's no option to check whether it is NULL or not (car exists or not). It will never be NULL.
Is there any other problems?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不会将您的代码称为
Singleton
,因为单例指的是给定类的单个实例(对象),并在整个应用程序运行时维护。没有什么可以阻止您的代码创建Car
类的多个实例,因此从某种意义上来说,car
不是单例(并且拥有并使用Car 的多个实例) car
由Vehicles
中的setter
方法隐含。我认为您想要实现的目标是确保调用链
vehicles.getCar().getWheelCount()
永远不会抛出NullPointerException
,这将是正确的。在单线程场景中,您的代码可能会按预期工作,但是当您有多个线程在同一个
vehicles
对象上调用getCar()
时,可能会导致不良结果。想象一下,您有两个线程持有同一个vehicles
对象,并且它们都同时调用getCar()
。在这种情况下,有可能两者都将car == null
视为true
,并且都创建了car
对象。然后,调用this.car = newCar
的最后一个线程将设置vehicles
对象中的car
字段,并覆盖该值。话虽如此,您可以考虑
Vehicles
需要服务的确切目的:它是汽车工厂(即构造但不保存引用),还是需要保存所有曾经创建过的 car
对象(从这个意义上说,单个Car
实例是不够的)。如果它可以用作工厂,那么您只需提供一个返回新创建的
Car
实例的方法newCar
即可简化Vehicles
。如果它应该保存汽车作为参考,那么您应该保留汽车的
集合
,并确保该集合可以同时修改。I wouldn't call your code a
Singleton
because singletons refer to a single instance (object) of a given class, maintained throughout the whole application runtime. There's nothing stopping your code from creating multiple instances of theCar
class, so in a sense thecar
is not a singleton (and having and using multiple instances of acar
is implied by thesetter
method inVehicles
).What I see you are trying to achieve, is to ensure that the call chain
vehicles.getCar().getWheelCount()
never throws aNullPointerException
, and that will be true.Your code may work as desired when in a single-thread scenario, however may lead to undesirable outcomes when you have multiple threads calling
getCar()
on the samevehicles
object. Imagine you have two threads that hold the samevehicles
object, and they both callgetCar()
at the same time. In such a situation, it is possible that both seecar == null
astrue
, and they both create acar
object. Then the last thread to callthis.car = newCar
will set thecar
field in thevehicles
object, overwriting the value.Having said that, you can think about what exact purpose
Vehicles
needs to serve: is it a factory for cars (i.e. construct but don't hold references), or does it need to hold allcar
objects that have been created ever (in that sense a singleCar
instance is not sufficient).If it can serve as a factory, then you can simplify
Vehicles
by simply providing a methodnewCar
that returns a newly createdCar
instance.If it should hold cars as references, then you should keep a
collection
of cars, and make sure this collection can be concurrently modified.这是一个“固执己见”的问题,但对此有一个简单的事实答案:团队内的惯例比“更全球化”的惯例更重要。
含义:从概念上讲,
getter()
应该就是“读取”值并将其提供给调用者的方法。在 C++ 术语中,您会想到一个const
方法,它不改变所调用的对象的状态。但 getter 方法的一个关键方面是:它们不仅仅是简单的字段访问。事实上,客户端使用x = foo.getX()
而不是x = foo.x
来实现这一点:除了返回值之外,还可以执行“其他操作”。所以:是的,
getCar()
有时创建一个Car
对象可能会让一些读者感到惊讶,但是当你的团队理解这些方面并同意时“这就是我们想要的”,那么这对你来说没问题。因为你的团队考虑了这个问题,并做出了这个决定。当然:更有意义的解决方案是首先不将其称为 getter:为什么不重命名该方法,并将其称为
getWithCreateIfNeeded()
或类似的名称? !当然,另一个答案是正确的:您在此处显示的代码是不是线程安全的。时期。当在多线程环境中使用时,这是唯一可以造成真正损坏的东西。
This is sort of an "opinionated" question, but there is a simple factual answer to that: the conventions within your team matter more than "more global" conventions.
Meaning: conceptually, a
getter()
should be exactly that, a method that "reads" a value and provides that to the caller. In C++ terms, you would think of aconst
method that does not alter the state of the object it is called on. But a key aspect of getter methods is: they can be more than a simple field access. The fact that clients dox = foo.getX()
instead ofx = foo.x
allows for exactly that: doing "other things" besides returning a value.So: yes,
getCar()
sometimes creating aCar
object might be surprising to some readers, but when your team understands such aspects, and agrees "this is what we want", then that is okay for you. Because your team thought about it, and made that decision.Of course: the more meaningful solution would be to not call it a getter in the first place: why not rename that method, and call it
getWithCreateIfNeeded()
or something alike?!Also of course, the other answer is spot on: the code you are showing here is not thread safe. Period. When used in a multi threaded environment, that is the only thing that can create real damage.