3

I have a method which accepts an Object. The object is a list. The list could be any type. I would like to identify the type of list using reflection and create an instance of the list & iterate over it and print the results.

Different Types of List

List<Customer> customerList = new ArrayList<Customer>();
List<Service> serviceList = new ArrayList<Service>();
List<Product> productList = new ArrayList<Product>();

Method that accepts the list

public void printList(Object genericList){

// identify the type of list
// create the list object
// iterate over the list and print the values

}
Punter Vicky
  • 15,954
  • 56
  • 188
  • 315
  • I have a few clarification questions: 1. When you say "identify the type of list" do you mean identify whether it is an `ArrayList`, `LinkedList`, etc. or identify if the contained type is a `Customer`, `Service`, `Product`, etc. 2. When `printList()` creates the new list, does is have to be the same class as the `genericList`? For example, if `genericList` is an instance of `ArrayList`, can a variable called `newList` be an instance of `LinkedList`? 3. When "iterating over the list to print values" are you expecting that we iterate over the `newList` or the `genericList`? – entpnerd Jan 12 '16 at 18:51

4 Answers4

4

Because of type erasure, there's no way to tell the generic type of a collection at runtime (which incidentally makes Object genericList an oxymoron). But if you just want to print them out regardless of the type, you can just cast it to List<?>:

public void printList(Object obj){
    for (Object o : (List<?>)obj) {
        System.out.println(o.toString());
    }
}

If you need a more type-specific implementation, and you know the lists won't be empty, and you're confident that there's no overlap between list types (i.e. customerList cannot contain Products and vice-versa), then you can technically do something like this:

public void printList(Object obj){
    List<?> list = (List<?>)obj;
    Object firstElement = list.get(0);
    if (firstElement instanceof Customer) {
        printCustomers((List<Customer>)list);
    } else if (firstElement instanceof Product) {
        printProducts((List<Product>)list);
    } //...
}

Note that the compiler will complain about these casts, and for good reason. It has no way of knowing whether you're telling the truth about the generic type, at least not until you try reading a value from the list, at which point you'll get a ClassCastException if you've made a mistake.

shmosel
  • 49,289
  • 6
  • 73
  • 138
  • Can't ParameterizedType be used to identify the type ? If it can't be , assuming I have a way to identify the type , is it possible to recreate the object ? – Punter Vicky Jan 12 '16 at 07:19
  • @PunterVicky it can't. And if you're trying to create a type at runtime, there's no custom construction required. You can just cast it to any generic type you want, because the runtime environment doesn't know about your generic parameters. See my update. – shmosel Jan 12 '16 at 07:22
  • You could use a covariant List if `Customer,Product,Service` all inherit from the same class i.e. `BaseClass` and replace the code to `List extends BaseClass> list = (List extends BaseClass>)obj;` – Radu Ionescu Jan 12 '16 at 08:00
1

If you want to judge the data type of the object from a list and print out the value, I would like to say that judging might not need the reflection since instanceof would satisfy your need. To print out the value or to have more manipulations on the specific object you could use the java reflection. It's very fragile. Currently I just list the codes of a simple model. If you confirm this is what you need then we could discuss more.

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException{

    List<Customer> customerList = new ArrayList<>();
    List<Service> serviceList = new ArrayList<>();
    List<Product> productList = new ArrayList<>();
    List result = returnFunc();
    printList(result);

}


public static void printList(List genericList) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
    Object obj=null;
    String type = "";
    Class c1 = null;
    // identify the type of list
    if(genericList.get(0) instanceof Customer){
        c1 = Class.forName("Customer");
    }else if(genericList.get(0) instanceof Service){
        c1 = Class.forName("Service");
    }else if(genericList.get(0) instanceof Product){
        c1 = Class.forName("Product");
    }else{
        System.out.println("Error");
    }
    // create the list object
    Object instance = c1.newInstance();
    // iterate over the list and print the values
    for(Object o : genericList){
        System.out.println(o.toString());

    }
}
//to randomly output a list
public static List returnFunc(){
    ArrayList<List> tmp = new ArrayList<>();
    ArrayList<Object> list_customer = new ArrayList<>();
    list_customer.add(new Customer());
    ArrayList<Object> list_service = new ArrayList<>();
    list_service.add(new Service());
    ArrayList<Object> list_product = new ArrayList<>();
    list_product.add(new Product());
    tmp.add(list_customer);
    tmp.add(list_service);
    tmp.add(list_product);
    Random r = new Random();
    return tmp.get(r.nextInt(3));
}
Shawn. L
  • 403
  • 1
  • 3
  • 13
0

create interface and each class implement this interface that is,

public interface someInterface{
}


public class Customer implements someInterface{
}

etc...

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
  • Thank you. These are classes provided as part of a jar file. I would like to dynamically identify the type of list and recreate the list. – Punter Vicky Jan 12 '16 at 07:02
  • No I would like to identify the type ( generic type) of list using reflection and once it is identified would like to recreate the object , iterate over the object , determine the fields using reflection and print the values – Punter Vicky Jan 12 '16 at 07:10
0

Maybe this is not the best method, but it might get you there

try{ 
    List<Customer> list = (List<Customer>) genericList; 
    list.get(0).methodOfCustomer(); 
    isCustomer = true;}
catch(Exception e){
    isCustomer = false
}

And similar clauses for the rest.

In the end just test which of the boolean is true, or use any other way.

Radu Ionescu
  • 3,462
  • 5
  • 24
  • 43