我最近一直在用c#和Java编程,我很好奇初始化我的类字段的最佳位置在哪里。

我应该在申报时申报吗?:

public class Dice
{
    private int topFace = 1;
    private Random myRand = new Random();

    public void Roll()
    {
       // ......
    }
}

或者在构造函数中?:

public class Dice
{
    private int topFace;
    private Random myRand;

    public Dice()
    {
        topFace = 1;
        myRand = new Random();
    }

    public void Roll()
    {
        // .....
    }
}

我很好奇你们这些老兵认为最好的做法是什么。我想保持一致,坚持一种方法。


当前回答

我通常尝试构造函数不做任何事情,只是获取依赖项并初始化相关的实例成员。如果您想对类进行单元测试,这将使您的工作更加轻松。

如果要分配给实例变量的值不受要传递给构造函数的任何参数的影响,则在声明时分配它。

其他回答

当你不需要一些逻辑或错误处理时:

在声明时初始化类字段

当你需要一些逻辑或错误处理时:

在构造函数中初始化类字段

当初始化值可用时,这工作得很好 初始化可以放在一行上。然而,这种形式 初始化因为简单而有局限性。如果 初始化需要一些逻辑(例如,错误处理或 对于循环填充复杂数组),简单的赋值是不够的。 实例变量可以在构造函数中初始化,其中error 可以使用处理或其他逻辑。

来自https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html。

我认为有一个警告。我曾经犯过这样一个错误:在派生类内部,我试图“初始化at声明”从抽象基类继承的字段。结果是存在两组字段,一组是“base”字段,另一组是新声明的字段,这花费了我相当多的时间来调试。

教训:要初始化继承的字段,需要在构造函数内部进行。

保持一致很重要,但你要问自己这个问题: “我还有其他的构造函数吗?”

通常,我正在为数据传输创建模型,类本身除了作为变量的外壳外什么也不做。

在这些场景中,我通常没有任何方法或构造函数。对我来说,只为了初始化列表而创建构造函数会感觉很愚蠢,特别是因为我可以在声明中对它们进行内联初始化。

正如许多人所说,这取决于你的使用习惯。保持简单,不要做任何不必要的额外事情。

这不是对你关于最佳实践的问题的直接回答,但一个重要的和相关的复习点是,在泛型类定义的情况下,要么让编译器使用默认值初始化它,要么我们必须使用一个特殊的方法将字段初始化为它们的默认值(如果这对代码可读性绝对必要的话)。

class MyGeneric<T>
{
    T data;
    //T data = ""; // <-- ERROR
    //T data = 0; // <-- ERROR
    //T data = null; // <-- ERROR        

    public MyGeneric()
    {
        // All of the above errors would be errors here in constructor as well
    }
}

将泛型字段初始化为默认值的特殊方法如下:

class MyGeneric<T>
{
    T data = default(T);

    public MyGeneric()
    {           
        // The same method can be used here in constructor
    }
}

我的规则:

不要初始化声明中的默认值(null, false, 0, 0.0…) 如果没有改变字段值的构造函数形参,最好在声明中初始化。 如果字段的值因构造函数形参而改变,则将初始化放在构造函数中。 坚持练习(这是最重要的规则)。