0

Scenario: I have a hierarchy of subclasses all inheriting from a single distance ancestral class. All super classes in the hierarchy are abstract, so the only concrete classes are those without subclasses. I have an array:

AncestralClass[] someObjects1 = new AncestralClass[someLength];

The ancestralClass is the single super class at the top of the hierarchy that all other classes inherit from. This array is populated with different objects of the various concrete subclasses. For example:

someObjects1[4] = new SubclassObject();

... and so on.

I have a second array of the same exact form (same type, size, etc), but the second array uses the first array to populate itself with objects again belonging to the various concrete subclasses. To be more specific, the object type in an element in the second array, will be decided based on the object type found in the same element of the first array. So the problem I have is this: I won't know what is contained in the first array because its contents are generated randomly at runtime, therefore I will not know what the contents of the second array should be as they are dependent on the first array. I am not sure how to write the code that instantiates the new objects in the second array. Written in English, what I want to happen sounds so simple and easy. I want to loop through the second array, check the corresponding position in the first array, check what kind of object that is, and then instantiate a new object of that type in the second array. That right there is what I don't know how to code:

someObjects2[i] = new (subclass that someObjects1[i] belongs to)(); 

Question To be more general, I want to instantiate a new object that is a new instance of a class an existing object belongs to. How do I do this, and I'm sure there's multiple solutions, so which is better?

Erik
  • 503
  • 1
  • 7
  • 26
  • 1
    Well, there's always reflection. I'm not sure that's "better" though. What patterns have you tried so far? – markspace Nov 11 '14 at 18:10
  • long answer short "someObjects1[4].getClass().newInstance();", note that this requires that the SubclassObject has a constructor with no arguments – Ricardo Garza V. Nov 11 '14 at 18:12
  • That can be done with constructor params if needed: http://stackoverflow.com/questions/234600/can-i-use-class-newinstance-with-constructor-arguments – spudone Nov 11 '14 at 18:21

2 Answers2

0

It seems from your description that you know beforehand the set of possible concrete classes in the first array. You can do something like:

for (int i = 0; i < array1.length; i++) {
    if (array1[i] instanceof SubclassObject1) {
        array2[i] = new SubclassObject1();
    } else if (array1[i] instanceof SubclassObject2) {
        array2[i] = new SubclassObject2();
    }
    ....
}
Khalid
  • 2,212
  • 11
  • 12
  • I actually tried to do something just like this before coming here using "instanceof," but stopped for a couple of reasons. The code started to look confusing and sloppy with all the nested if-else statements and I had read to avoid the use of "instanceof." Would this style be frowned upon by other programmers. If I did use "instanceof," I would make a large if-else structure that followed the structure of the class hierarchy until I found the correct subclass, then use a statement with "new Subclass();" like you suggested. – user4240561 Nov 11 '14 at 19:32
  • If your concrete classes are stable with little/no changes, then I think this method is more readable and less complex that reflection or other convoluted methods. Yes, `instanceof` should not be abused, but I think this is an appropriate time for it. Also, you don't have to follow the hierarchy. Only check for the concrete classes. If you have 5 concrete classes, then you'll have 5 `if` tests. – Khalid Nov 11 '14 at 19:45
  • I think following the hierarchy would be more efficient if the number of concrete classes starts to get large. For example, if I had a class hierarchy that emulated the animal kingdom. Animal branches off to reptile and mammal and fish and ....and each of those subclasses could branch off...It would be more efficient to find Animal > reptile > lizard > iguana than to search through every single species every time this algorithm was used. – user4240561 Nov 11 '14 at 19:54
  • Using the statement: someObjects1[4].getClass().newInstance(); was mentioned above. Couldn't I use this one line of code to replace an entire if-else structure (that uses instanceof). – user4240561 Nov 11 '14 at 19:56
  • You can use it if all of your concrete classes have default no-argument constructors. – Khalid Nov 11 '14 at 20:38
0

I think this idea is sort of dubious. There's all sorts of problems you can run into trying to create classes of types you don't control in advance.

So if I did this, the first thing I would do is to use a simple factory method, which is the most basic creational pattern. This way you have all your code isolated in one spot, so if you need to change it later, you can. Then I would just use reflection to create the object.

public class Creation
{
   private Creation() {}

   public static <S, T extends S> S makeNew( T obj )
           throws InstantiationException, IllegalAccessException
   {
      return (S) ( obj.getClass().newInstance() );
   }

   // Demonstration
   public static void main( String[] args )
           throws InstantiationException, IllegalAccessException
   {
      CharSequence[] cs = { new StringBuilder(), new Segment()  };
      for( CharSequence c : cs ) System.out.println( makeNew( c ) );
   }
}

This will work for simple cases. If you need to use a fancy library like Objenesis in the future, you have an easy place to make your changes.

markspace
  • 10,621
  • 3
  • 25
  • 39