例如:
public class App {
private Car car = new Car();
public static void main(String[] args) {
// TO DO
}
}
如果不好,有什么解决办法?你会如何重写这段代码?
我一直被教导,声明应该放在前面,初始化应该放在内部。在构造函数内部初始化更加高效,因为如果你需要在构造时使用传递的参数来改变它,你可以直接初始化而不是初始化和赋值。
例如:
public class TestClass{
//Declared but uninitialized
Object obj;
//Makes no difference but easier to read
public TestClass(){
this.obj = new Object();
}
//In this constructor however the object being passed in is what is initializing obj
//-so if you were to initialize it above and then change it down here you are writing
//-to the mem twice and it is less efficient.
public TestClass(Object arg){
this.obj = (Object)arg;
}
}
如果程序将“始终”需要对象实例并且创建实例的成本不太高(时间、资源),则可以在声明中初始化对象。然后,是的,可能需要这种类型的“急切初始化”。
然而,这种设计违反了OO设计,使类保持松散耦合,并使单元测试更加困难。
例如:
public class App {
private Car car = new Car();
}
public class App {
private Car car;
App() {
}
// overloaded constructor
App(Car car) {
this.car = car;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public static void main(String[] args) {
// default constructor, lightweight, no car initialization happening;
App ap1 = new App();
// Ok, now I want a car, and it should be red.
Car redCar = new Car("red");
ap1.setCar(redCar);
// Using overloaded constructor, now I can control aspects of "car"
Car blueCar = new Car("blue");
App ap2 = new App(blueCar);
}
}
如果你想让你的代码更容易测试,这是一个不好的做法。原因是创建 App
也会创建一个 Car
,无论你是否需要它。现在,如果 Car
有连接到数据库的代码,那么当你测试 App
时,你需要有一个可用的数据库可以连接,否则你的测试将失败。
解决方案是依赖注入,也称为控制反转。你可以这样写:
public class App {
private Car car;
public App(Car car) {
this.car = car;
}
public static void main(String[] args) {
// TO DO
}
}
现在创建 App
不一定会创建一个 Car
,它们耦合程度较低。
现在,我在这里非常严谨。我可能一直在我的代码中使用您的示例。我只是指出了一个缺点。这并不总是坏的,也不总是好的。
请注意,“meaning”和“意义”之间有区别:
public class App {
private Car car = new Car();
public static void main(String[] args) {
// TO DO
}
}
并且
public class App {
private Car car;
public App(){
car = new Car();
}
}
public class App{
private Car car;
public Car getCar(){
return car;
}
public void setCar(Car car){
this.car = car;
}
public App(Car car){
this.car = car;
}
}
这个,我想,是面向对象类最常见的结构。
private Car car;
public static void main(String[] args)
{
App app=new App(); //
app.car. //Followed by the method or the member variable that you would like to
//access
}
}
main
函数中的代码看起来像那样。我特别指的是直接设置自己的字段。我不建议这种做法。这会让某人创建一个 App
并在以后出现 NPE。如果你将它传递到构造函数中,你可以更快地失败。 - Daniel Kaplanprivate Car car;
public App() {
this.car = null;
}
public void Init() {
this.car = new Car();
}
public void Shutdown() {
this.car = null;
}
public static void main(String[] args) {
App app = new App();
app.Init();
app.Shutdown();
app = null;
}
}
private Car car = new Car();
我认为这是完全可以的。不进行该操作的几个原因如下:
Car.<init>
需要参数,这些参数仅在App.init
中可用。App
有许多字段,其他字段需要在App.<init>
中初始化,为了保持一致性,您希望将它们全部放在一起。无论如何,请不要执行以下操作:
private Car car = null;
因为每个Java开发人员都知道实例字段被初始化为null
。