【问题标题】:Deep copy and returning an instance Java深拷贝并返回实例 Java
【发布时间】:2016-10-28 23:05:22
【问题描述】:

所以我正在做一个大学一年级作业的问题,我会诚实地对待它。我只是想在你们中的一些人对我的问题投反对票之前把事情说清楚。我不想要完整的代码,我只是想要一些帮助。

问题分为两部分。第一部分是编写一个 Nucleotide 类,它的构造函数有两个属性。称为 base 的单个字符必须是 'a' 或 'c' 或 'g' 或 't' 否则它应该是 'n' 和一个称为 degenerate 的布尔值。

这部分的代码在这里:

class Nucleotide {
    private char base;
    private boolean degenerate;

    public nucleotide(char base, boolean degenerate){
      if(base != ‘a’ || base != ‘c’ || base != ‘g’ || base != ’t’){
        this.base = ’n’;
      } else {
          this.base = base;
      }
      this.degenerate = degenerate;
    }
}

问题的下一部分说使用 Nucleotide 对象并创建一个新的 Bacteria 类。一个细菌实例由一个基因组(核苷酸的集合)和一个物种(一个字符串)组成。

您必须创建一个接受字符串和集合的构造函数,并使用它们来 初始化物种和核苷酸的集合。 我这部分的代码在这里:

class Bacteria {
  //private ArrayList<Nucleotide> genome;
  private String species;

  public Bacteria(String species, ArrayList<Nucleotide> genome) {
    genome = new ArrayList<Nucleotide>();
    this.species = species;
  }

我的问题从下一步开始,它要求我们编写一个实例方法来执行深度复制并返回一个 Bacteria 实例。

public Bacteria binaryFission() {

如何在没有序列化和反射的情况下执行深层复制。我对那些事情几乎一无所知。

我再次需要指针或关于如何完成binaryFission() 方法的基本概念。 我已经处理了几个关于 SO 的深层复制问题,但它们都与我的问题无关,所以我不认为我在问重复的问题。我很乐意提供更多详细信息.

【问题讨论】:

  • 你为什么把//private ArrayList&lt;Nucleotide&gt; genome;注释掉了?
  • 创建一个新列表。遍历核苷酸,并创建每个核苷酸的副本。将副本添加到新列表中,然后通过使用该新列表调用构造函数来创建一个新的 Bacteria 实例。您不需要复制字符串,因为它是不可变的,因此可以在实例之间安全地共享。
  • 因为那会复制代码,我相信。我在构造函数中也有该代码。通过获取构造函数的 ArrayList,我可以从那里初始化列表。我的逻辑对那部分有错吗? @波西米亚
  • 您需要学习基础知识,了解字段、局部变量和参数之间的区别。您的构造函数将列表作为参数,但完全忽略它,甚至用新的空列表覆盖它。您需要对参数做一些事情,或者将其存储在字段中以供以后使用,否则该参数是无用的。
  • 我只是在我的构造函数中做这部分您必须创建一个接受字符串和集合的构造函数,并使用它们来初始化物种和核苷酸集合。这也是我注释掉基因组实例变量的原因之一。如果我取消注释基因组并在构造函数中获得一个列表,那么我将如何初始化它们? @JBNizet

标签: java class clone deep-copy


【解决方案1】:

这是手动操作的方法

public Bacteria binaryFission() {
    String speciesClone = this.species;
    ArrayList<Nucleotide> genomeClone = new ArrayList<Nucleotide>();
    //now iterate over the existing arraylist and clone each Nucleotide
    for(int index = 0; index < this.genome.size(); index++)
    {
        genomeClone.add(new Nucleotide(
                            genome.get(index).getBase(), //needs to be added to the Nucleotide class to retrieve the base variable
                            genome.get(index).getDegenerate() //needs to be added to be allowed to get its degenerate
                ));
    }

    return new Bacteria(speciesClone, genomeClone);
}

仅供参考 - 您需要为您的 Nucleotide 类私有变量添加 getter 才能正常工作,因为它们是私有的,没有它们,细菌将无法访问它们的值。

【讨论】:

  • 为什么不使用 foreach 循环而不是使用索引循环?它会使代码更简洁。
  • 是的,这是一个糟糕的主意:它们更冗长,更容易出错,而且链表效率极低。
【解决方案2】:

由于Nucleotide 没有设置器,并且它的字段是原始的,因此它实际上是不可变的(无法更改,因此可以安全地“重用”)。您最好将字段设置为 final 以正式使其不可变。

制作深拷贝所需要做的就是制作 Nucleotide 列表的浅拷贝,然后在新的 Bacteria 中使用它。你可以这样复制:

List<Nucleotide> copy = new ArrayList<>(genome);

您可以在 Bacteria 上创建一个简单的工厂方法,该方法返回其自身的深层副本:

public Bacteria copy() {
   return new Bacteria(species, new ArrayList<>(genome));
}

【讨论】:

  • 这是我的第一个想法,但鉴于发布的代码无法编译,并且没有任何方法使该类可用,很难说它在现实中确实是不可变的。跨度>
  • @JBN 都是真的,但如果它没有用,那么 OP 很快就会发现这个事实,他会解决这个问题。或者它可以是一个直接访问其字段的内部类,或者可以省略 getter。无论如何,原始(最终)字段是这里的重要部分。
  • 我觉得你很乐观:-)
猜你喜欢
  • 2015-04-25
  • 1970-01-01
  • 2013-01-26
  • 2012-04-13
  • 2016-12-03
  • 2012-10-14
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多