【问题标题】:Assigning value of an object to another - they mustn't point same adresses at memory将一个对象的值分配给另一个对象-它们不能将相同的地址指向内存
【发布时间】:2011-03-16 20:54:15
【问题描述】:

我在获取对象的新值时遇到问题。我有这样的代码:

...
TimeSchedule[] offspringScheduleOne = new TimeSchedule[AVAILABLE_CLASSROOMS];
...
offspringScheduleOne[i] = genes.get(geneOneIndex).getSchedule()[i];
...

在赋值后,offspringScheduleOne[i] 和genes.get(geneOneIndex).getSchedule()[i] 指向相同的内存地址。我想要:offspringScheduleOne[i] 应该得到 genes.get(geneOneIndex).getSchedule()[i] 的值,它们不能相同,它们应该具有相同的值

TimeSchedule 类:

public class TimeSchedule extends AlgorithmParameters {
    public int[][] timetable = new int[DAYS][HOURS];//DAYS and HOURS are static final variables that comes from AlgorithmParameters 

    public int[][] getTimetable() {
        return timetable;
    }

    public void setTimetable(int[][] timetable) {
        this.timetable = timetable;
    }
}

我该怎么做?

【问题讨论】:

  • 您的问题的标题(它们必须在内存中指向相同的地址)与文本相反(它们应该具有相同的值 ) - 事实上,你想要什么?
  • @Paŭlo Ebermann 谢谢,我已经编辑过了。

标签: java memory variable-assignment


【解决方案1】:

它实际上 复制了该值 - 但您需要了解该值是什么。

offspringScheduleOne[0] 的值不是 TimeSchedule 对象。这是对TimeSchedule 对象的引用Java 中没有表达式的值是对象。理解这一点非常重要。

现在,如果您想要对象的副本,您必须自己实现。例如,您可以在TimeSchedule 中包含clone() 方法,并编写:

offspringScheduleOne[i] = genes.get(geneOneIndex).getSchedule()[i].clone();

换句话说,创建现有对象的克隆,然后将offspringScheduleOne[i] 设置为对该新创建对象的引用。当然,如果TimeSchedule 中的任何字段是引用类型字段,您需要考虑是否也需要克隆 那个 对象...

... 或者您可以添加一个构造函数并调用它,或者其他方法等。但是您需要绝对清楚赋值运算符 复制值,但该值是参考。

编辑:好的,既然你已经发布了TimeSchedule,一些建议:

  • 停止使用公共字段。如果字段是公开的,那么拥有属性有什么意义?
  • 与其让属性返回整个数组,不如将它们更改为访问单个小时,例如

    public int getTimetable(int day, int hour) {
        // TBD: Argument validation
        return timetable[day][hour];
    }
    
    // Similar for `setTimetable`
    
  • 像这样创建一个克隆方法:

    public TimeSchedule clone() {
        TimeSchedule copy = new TimeSchedule();
        for (int i = 0; i < timetable.length; i++) {
            copy.timetable[i] = timetable[i].clone();
        }
        return copy;
    }
    

    (这有点浪费,因为它会创建子数组然后丢弃它们,但让我们先得到一些有用的东西......) }

    公共测试克隆(){ int[][] timetableCopy = new int[timetable.length][]; for (int i = 0; i

【讨论】:

  • 我已经编辑了我的代码并包含了 TimeSchedule 类的代码。你建议写什么克隆方法?
  • @kamaci:基本上你需要在 TimeSchedule 中克隆数组。将编辑。
  • 我会考虑您的建议。你的解决方案非常好。接受您的回答并投票支持您的额外建议。谢谢。
【解决方案2】:

您应该创建一个新的 TimeSchedule 对象。假设您有一个复制构造函数,您可以使用它:

TimeSchedule original = genes.get(geneOneIndex).getSchedule()[i];
TimeSchedule copy = new TimeSchedule(original);
offspringScheduleOne[i] = copy;

构造函数应该复制原始值。如果您没有这样的构造函数,您可以调用 get 和 set 方法来手动复制值。

TimeSchedule original = genes.get(geneOneIndex).getSchedule()[i];

TimeSchedule copy = new TimeSchedule();
copy.setFoo(original.getFoo());
copy.setBar(original.getBar());
// etc...

offspringScheduleOne[i] = copy;

还有一个clone 方法是为创建对象的副本而设计的,但是使用起来很尴尬,最好避免使用它。

【讨论】:

  • 我读了你的回答,我想了解更多关于克隆方法的信息。 Jon Skeet 的回答如何?覆盖该克隆方法或您的答案,您可以比较它们哪个更好吗?
【解决方案3】:

你可以让 TimeSchedule 覆盖 clone 方法并编写

offspringScheduleOne[i] = genes.get(geneOneIndex).getSchedule()[i].clone();

【讨论】:

    猜你喜欢
    • 2019-12-27
    • 2016-06-24
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    • 2020-11-10
    相关资源
    最近更新 更多