Hu Liu
Hu Liu

Reputation: 3

How to make copy of the contents of an array without knowing the specific subtype of its contents?

Say I have an abstract class called SuperClass and many classes extending it. I have an array of of type SuperClass[]. I want to make an array with new objects of the same subclasses and the same attributes.

I tried to do this by creating instantiating new objects and fill the new array with them. However this doesn't work as demonstrated as follows.

SuperClass[] newArray = new SuperClass[arr.length];
for (int i = 0; i <= arr.length; i++) {
    SuperClass toBeCopied = arr[i];
    newArray[i] = new SuperClass(toBeCopied.attribute1, toBeCopied.attribute2...);

This does not work because SuperClass is abstract and thus cannot be instantiated.

I also looked at .clone(), but SuperClass doesn't extend Cloneable.

Are there any other ways of making a copy of an array with unknown content types?

Upvotes: 0

Views: 409

Answers (2)

Swapnil Patil
Swapnil Patil

Reputation: 613

You can use reflection to do so

SuperClass[] newArray = new SuperClass[arr.length];
for (int i = 0; i <= arr.length; i++) {
  SuperClass toBeCopied = arr[i];
  newArray[i] = (SuperClass) Class.forName(toBeCopied.getClass().getName())
      .getConstructor(String.class, String.class)
      .newInstance(new Object[] { toBeCopied.getAttribute1(),toBeCopied.getAttribute2() });
}

Here i am considering, your constructor with two parameters of String type. If you have different type of parameters then change the type at .getConstructor(String.class, String.class).

Sub Type(Class)

public class SubType1 extends SuperClass{
  public SubType1(String attribute1, String attribute2) {
    super(attribute1, attribute2);
  }
}

public class SubType2 extends SuperClass{
  public SubType2(String attribute1, String attribute2) {
    super(attribute1, attribute2);
  }
}

Super Class

public abstract class SuperClass {
private String attribute1;
private String attribute2;

public SuperClass(String attribute1, String attribute2) {
    // TODO Auto-generated constructor stub
    this.attribute1 = attribute1;
    this.attribute2 = attribute2;
}

public String getAttribute1() {
    return attribute1;
}

public void setAttribute1(String attribute1) {
    this.attribute1 = attribute1;
}

public String getAttribute2() {
    return attribute2;
}

public void setAttribute2(String attribute2) {
    this.attribute2 = attribute2;
}
}

Upvotes: 0

priyanksriv
priyanksriv

Reputation: 1154

There's a set of static methods in Arrays that can copy an array. For example: <T> T[] copyOf(T[] original, int newLength). Usage:

abstract class SuperClass {  }

class SubClass extends SuperClass {  }

// copy
SuperClass[] subClasses = new SubClass[10];
SuperClass[] subClassesCopy = Arrays.copyOf(subClasses, 10);

-- Update --

Since you want copies of each object within the array, you can define an abstract method in SuperClass and have the subclasses extend it.

  abstract class SuperClass {

    public abstract SuperClass deepCopy();
  }

  class SubClass extends SuperClass {

    private String value;

    public SubClass(String value) {
      this.value = value;
    }

    @Override
    public SubClass deepCopy() {
      return new SubClass(this.value);
    }
  }

And then call deepCopy in your code:

    SuperClass[] subClasses = new SubClass[] { new SubClass("1"), new SubClass("2") };

    SuperClass[] subClassesCopy = Arrays.stream(subClasses)
        .map(orig -> orig.deepCopy())
        .collect(Collectors.toList())
        .toArray(new SuperClass[subClasses.length]);

Upvotes: 1

Related Questions