0

Say I have two classes Foo and Bar which implement interface A. I either want to make an ArrayList of Foo or Bar. In the command line arguments, the user must input either Foo or Bar as to which object they are trying to make an ArrayList of.

So:

public static void main(String [] args){
    String type = args[0];
    ArrayList<type> list = new ArrayList<type>();
    }

How do I go from the string type to a reference to the class Foo or Bar so it's doing

ArrayList<Foo> list = new ArrayList<Foo>();
or
ArrayList<Bar> list = new ArrayList<Bar>();

This way I can do the following:

for(int i = 0 ; i < list.size() ; i++){
    list(i).doSomething();
    //doSomething is a function in interface A that Foo and Bar are required to implement
}    

To be clear, I don't want something like

if (type.equals("Foo")) list = ArrayList<Foo>();

I want to be able to make an ArrayList with any valid class with the same name as type.

Dan Smith
  • 43
  • 1
  • 7

6 Answers6

1

The compiler will need to know the type, and it sounds like you want to treat the type as a runtime variable instead of a compile-time fact.

Check out Get generic type of class at runtime. It essentially asks the same thing and you'll get good information about a possible workaround solution using reflection.

Community
  • 1
  • 1
Shawn
  • 8,374
  • 5
  • 37
  • 60
1

This is not possible in Java. You can, using reflection, retrieve a type name, but there's no way to create a generic type dynamically.

The reason is that generic types exist at compile time only and are used by the compiler to enforce static type safety. At runtime, the generic information is discarded, so it's not even meaningful (in the current Java philosophy) to do what you are asking. At runtime, generic types have been converted to Object, with the compiler having substituted type-safe casts where necessary.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
0

Use Class.forName(String classNameWithPath) method - it will do what you want.

There is an example over here - What is the difference between "Class.forName()" and "Class.forName().newInstance()"?

Community
  • 1
  • 1
user
  • 3,058
  • 23
  • 45
0

Declare the array list as an ArrayList<A>. That way it can store both Foo and Bar objects, because they both implement the interface A.

Philipp
  • 67,764
  • 9
  • 118
  • 153
  • I realize I can do this but I would like to be able to do it for any class, regardless of what it implements. I was providing more context as to why I wanted to do this. Thanks, though. – Dan Smith May 01 '13 at 22:37
0

You could maintain a list of all of the possible types that implement that interface and then iterate over their types until you find one that matches the input string. Other than that I think you will have trouble doing this in Java.

placeybordeaux
  • 2,138
  • 1
  • 20
  • 42
0
public class ForNameTest {
public static void main(String[] argv) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    java.util.ArrayList<String> arrayList = null;
    try {
        Class<?> createdClass = Class.forName("java.util.ArrayList<java.lang.String>");
        arrayList = (java.util.ArrayList<String>) (createdClass.newInstance());
        arrayList.add("ABC");
        System.out.println("First case " + arrayList.toString());
    }
    catch (ClassNotFoundException e) {
        System.out.println("Exception in first case: " + e.toString());
    }
    try {
        Class<?> createdClass = Class.forName("java.util.ArrayList");
        arrayList = (java.util.ArrayList<String>) (createdClass.newInstance());
        arrayList.add("ABC");
        System.out.println("Second case " + arrayList.toString());
    }
    catch (ClassNotFoundException e) {
        System.out.println("Exception in second case: " + e.toString());
    }
}
}

Output:

C:\JavaTools>javac ForNameTest.java
Note: ForNameTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

C:\JavaTools>java ForNameTest
Exception in first case: java.lang.ClassNotFoundException: java.util.ArrayList<java.lang.S
tring>
Second case [ABC]

(Not sure what this proves -- you still can't declare your ArrayList to be of variable (vs <?>) type. But there it is, FWIW.)

Hot Licks
  • 47,103
  • 17
  • 93
  • 151