6

I have a hierarchy where Square, Triangle and Circle all extend from Shape. I have a working method:

public void someMethod() {
   File file = new File("File_with_squares");
   ThirdPartyClass foo = new ThirdPartyClass();
   Square[] squares = foo.someMajicMethod(Square[].class,file);
   for (Square square: squares) 
      square.draw();

}

Now I want to make this method generic so that it can accept any shape. I want to be able to call it someMethod(Triangle.class,new File("File_with_triangles") or someMethod(Circle.class, new File("File_with_circles"). I am trying like this:

public void someMethod(Class<? extends Shape> type, File shapeFile) {
   ThirdPartyClass foo = new ThirdPartyClass();
   #### What goes here??? ####
   for (Shape shape: shapes)
       shape.draw();
}

What should be there at #### What goes here??? #### ???

Mohamed
  • 193
  • 3
  • 10

3 Answers3

6

Perhaps Array.newInstance(..) is of interest for you

Omnaest
  • 3,096
  • 1
  • 19
  • 18
  • 1
    he's not creating an array anywhere in this method – newacct Aug 15 '11 at 20:35
  • @newacct no he is not, but at one point in his majic method he might want to. There are not that much possibilities if you take object serialization away. And this seems to me the point of interest to create this array by his generic type argument. Or do you think I am wrong with that assumption? – Omnaest Aug 16 '11 at 16:08
6

Assuming ThirdPartClass.someMajicMethod has a signature something like this:

public <T> T someMajicMethod(Class<T> class1, File file);

Then you should be able to do something like this:

public void someMethod(Class<? extends Shape> type, File shapeFile) {
    ThirdPartyClass foo = new ThirdPartyClass();

    @SuppressWarnings("unchecked")
    Class<? extends Shape[]> arrayType = 
        (Class<? extends Shape[]>) Array.newInstance(type, 0).getClass();
    assert Shape[].class.isAssignableFrom(arrayType);

    Shape[] shapes = foo.someMajicMethod(arrayType, shapeFile);

    for (Shape shape: shapes)
        shape.draw();
}

So if you call someMethod(Triangle.class, file), then arrayType will be Triangle[].class in the call to someMajicMethod.

Though you may find it simpler to have someMethod take the array type as a parameter instead of the element type so you can avoid that step.

avh4
  • 2,635
  • 1
  • 22
  • 25
  • how about simply `assert Shape.class.isAssignableFrom(type)`? – newacct Aug 16 '11 at 14:39
  • `type`'s type is already enforced by the compiler. I'm asserting `arrayType`'s type because we've just done an unchecked cast (the generic type info is going to be erased at compile time). And also, asserts in Java won't execute unless you enable them explicitly in the VM. Asserts are better used as documentation than as enforcement. In this case, I can guarantee that that assert will alway pass unless `Array.newInstance` is broken. – avh4 Aug 16 '11 at 15:09
3
Shape[] shapes = foo.someMajicMethod(type, file);

If foo is a third-party class, I assume you don't control the API of it. I assumed it has the appropriate method signature to handle the line I've written but there is no way for me to be certain without more information about that class.

If this doesn't work, what is the problem?

Jesse Webb
  • 43,135
  • 27
  • 106
  • 143
  • It's a good thing that someMajicMethod returns an array, if it was a List, it would be more complicated. Square[] can be cast to Shape[], but not List to List. – toto2 Aug 15 '11 at 19:36
  • My reading of the question was that if you pass `Triangle.class` to someMajicMethod, then it is going to return a Triangle, not a Triangle[] – avh4 Aug 15 '11 at 19:37
  • 1
    @Aaron Maybe Mohamed should change is method to `someMethod(Class extends Shape[]> type,...)`. – toto2 Aug 15 '11 at 19:43
  • Yes. I made it work by making someMethod take array type. So it went like this : someMethod(Class extends Shape[]> arrayType, File shapeFile) { Shape[] shapes = foo.someMajicMethod(arrayType,shapeFile) } – Mohamed Aug 15 '11 at 20:14
  • @Mohamed - Glad it worked for you! Don't forget to accept an answer if you solved your problem. – Jesse Webb Aug 19 '11 at 20:36