什么时候给Java中的实例变量赋值合适?

When is it appropriate to assign values to an instance variable in Java?

这是一个关于最佳实践的问题。在采用面向对象的方法时,我想出了三种不同的方法来做同样的事情。在我未经训练的眼中,none 其中似乎 "wrong",但我知道每种语言和风格都有其最佳实践,我想知道这三种方式中的任何一种是否违反了某些 "best practice"我还没学会

方式一:(声明,然后在构造函数中赋值)

public class CCipher {

    private String alphabet;
    private String shiftedAlphabet;
    private int mainKey;

    public CCipher(int key){

        mainKey = key;
        alphabet = "abcdefghijklmnopqrstuvwxyz";
        shiftedAlphabet = alphabet.substring(mainKey) 
                        + alphabet.substring(0, mainKey);
    }

方式二:(同时声明和赋值)

public class CCipher {

    private String alphabet = "abcdefghijklmnopqrstuvwxyz";
    private String shiftedAlphabet;
    private int mainKey;

    public CCipher(int key){

        mainKey = key;
        shiftedAlphabet = alphabet.substring(mainKey) 
                        + alphabet.substring(0, mainKey);
    }

方式 3:(有些东西在非 get/set 方法中初始化)

public class CCipher {

    private String alphabet;
    private String shiftedAlphabet;
    private int mainKey;

    public CCipher(int key){

        mainKey = key;
        alphabet = "abcdefghijklmnopqrstuvwxyz";

    }

    public String encrypt(String input){
        shiftedAlphabet = alphabet.substring(mainKey) 
                        + alphabet.substring(0, mainKey);
        // ... code to encrypt input ...
    }

    public String decrypt(String input){
        shiftedAlphabet = alphabet.substring(26 - mainKey) 
                + alphabet.substring(0, 26 - mainKey);
        // ... code to decrypt input
    }
}

就我个人而言,对于这个特定的家庭作业,我真的最喜欢第三种方式,因为它符合我要解决的问题的逻辑。但它错了,错了......

第二个版本好像还行。但是常量确实是 st​​atic final String.

public class CCipher {

    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
    private final String shiftedAlphabet;
    private final int mainKey;

    public CCipher(int key) {
        mainKey = key;
        shiftedAlphabet = ALPHABET.substring(mainKey) 
                        + ALPHABET.substring(0, mainKey);
    }

Christopher Schneider 指出在加密和解密中使用了不同的 shiftedAlphabet。由于 CCipher 对象实际上可能加密或解密,因此将其设为局部变量。

需要两个不同的非最终延迟初始化字段,这很麻烦。

public class CCipher {

    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
    //private final String shiftedEncryptAlphabet;
    //private final String shiftedDecryptAlphabet;
    private final int mainKey;

    public CCipher(int key) {
        mainKey = key;
        shiftedAlphabet = ALPHABET.substring(mainKey) 
                        + ALPHABET.substring(0, mainKey);
    }

    public String encrypt(String input){
        String shiftedAlphabet = alphabet.substring(mainKey) 
                    + alphabet.substring(0, mainKey);
        // ... code to encrypt input ...
    }

    public String decrypt(String input){
        String shiftedAlphabet = alphabet.substring(26 - mainKey) 
            + alphabet.substring(0, 26 - mainKey);
        // ... code to decrypt input
    }

关于 alphabet - 如果它从未改变,第二个片段可能最接近最佳实践,但它仍然不完全 - 它应该是 private static final "constant":

public class CCipher {   
    private static final String alphabet = "abcdefghijklmnopqrstuvwxyz";
    // ...
}

关于 shiftedAlphabet - 第三个片段肯定不太受欢迎(尽管在技术上不是 "wrong") - 在每次调用 encryptdecrypt 时,您都会重新计算shiftedAlphabet 不受 input 的任何影响。这可能没有错,但很浪费(换句话说-作为老师,我肯定会为此扣分,即使代码确实有效)。

总而言之 - 第二个片段可能是所有三个片段中最好的,但我会将 alphabet 的修饰符修改为 private static final