2

我必须创建一个电影的深拷贝构造函数,它应该具有与提交对象相同的序列。我认为第一步已经正确,但是当我尝试:“this.serial = that.serial”时,它会发出警告并说我无法覆盖最终变量。

当我删除final关键字时,我可以解决这个问题,但这是不允许的。任何人都可以在不删除 final 关键字的情况下帮助我更改最终的 int 串行变量吗?

private int serial;
private String title;
private FSK fsk;
private boolean isRent;

private final int serial;
private static int nextSerial;

Movie(String title, FSK fsk) {
    this.title = title; 
    this.fsk = fsk;
    this.serial = nextSerial;
    nextSerial++;

}
Movie(Movie that) {
    this(new String(that.title), that.fsk);
    this.serial = that.serial;
    }
4

4 回答 4

2

不要调用其他构造函数:this(new String(that.title), that.fsk);

您收到此错误是因为 this.serial 正在您调用的其他构造函数中设置。一旦设置了最终变量,就不能再次设置它。这就是你收到错误的原因。

于 2013-06-24T17:49:28.777 回答
1

正如 aglassman 所指出的,您最终会设置serial两次 - 一次在链式构造函数中,另一次在调用它的构造函数中。你不被允许这样做。(我怀疑你也不想增加nextSerial。)

我建议您创建一个设置所有字段的构造函数 - 然后从其他构造函数调用它。例如:

Movie(String title, FSK fsk) {
    // Note: Change nextSerial to an AtomicInteger
    this(title, fsk, nextSerial.incrementAndGet());
}

Movie(Movie that) {
    this(that.title, that.fsk, that.serial);
}

private Movie(String title, FSK fsk, int serial) {
    this.title = title;
    this.fsk = fsk;
    this.serial = serial;
}

请注意,没有必要使用new String(that.title),因为字符串已经是不可变的。此外,我已将您的使用更改nextSerial为使用 an AtomicInteger,否则您将遇到线程安全问题。

于 2013-06-24T17:51:56.383 回答
0

您不能定义一个字段然后再次定义它。

private int serial;
...
private final int serial;
于 2013-06-24T17:54:53.553 回答
0

我在这里会有点笨拙,但是请在投票之前坚持下去并阅读整个回复;)首先,您不能更改最终字段是不正确的。在 Java 中,你几乎可以做任何事情;)检查一下:

    public class Movie {

    static class FSK { /* TODO */ }

    private String title;
    private FSK fsk; 
    private boolean isRent;
    private final int serial;
    private static int nextSerial;

    Movie(String title, FSK fsk) {
        this.title = title;
        this.fsk = fsk;
        this.serial = nextSerial;
        nextSerial++;

    }

    Movie(Movie that) {
        this(new String(that.title), that.fsk);
        setFinalSerial(that.serial);
    }

    void setFinalSerial(int newValue) {
        try {
            java.lang.reflect.Field field = getClass().getDeclaredField("serial");
            field.setAccessible(true);

            java.lang.reflect.Field modifiersField = java.lang.reflect.Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(field, field.getModifiers() & ~java.lang.reflect.Modifier.FINAL);

            field.set(this, newValue);
        } catch (Exception exception) {
            throw new RuntimeException(exception);
        }
    }

        /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       Movie m1 = new Movie("title", new FSK());
       Movie m2 = new Movie(m1);
       System.out.println(m1.serial);
       System.out.println(m2.serial);
    }
}

但这只是一个丑陋的把戏。我猜你的课应该是这样的:

    public class Movie {

    static class FSK { /* TODO */ }

    private String title;
    private FSK fsk; 
    private boolean isRent;
    private final int serial;
    private static int nextSerial;

    Movie(int serial, String title, FSK fsk) {
        this.title = title;
        this.fsk = fsk;
        this.serial = serial;
    }

    Movie(String title, FSK fsk) {
        this (nextSerial++, title, fsk);
    }

    Movie(Movie that) {
        this(that.serial, that.title, that.fsk);
    }

        /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       Movie m1 = new Movie("title", new FSK());
       Movie m2 = new Movie(m1);
       System.out.println(m1.serial);
       System.out.println(m2.serial);
    }
}

关键是您应该创建“复制构造函数”,您可以在其中设置最终变量而无需任何技巧。

于 2013-06-24T18:09:27.400 回答