简体   繁体   中英

JAVA - cast using class obtained by its name (string value)

this is what my code looks if I use a predefined class:

List<MyClass> result = new ArrayList<MyClass>();
try {
    Query query = mgr.newQuery(MyClass.class);
    for(Object obj : (List<Object>) query.execute()) {
        result.add(((MyClass) obj));
    }
}
.... 
return result;

now I need to be more generic: starting from a generic class name (as a string, ie "TheChosenOne") I need to do the same thing, but I can't figure out how the cast part should be done..

Just to make an example of what I'm trying to do:

String str = "TheChosenOne"; //this value may change
Class cls;
List<Object> result = new ArrayList<Object>();
try {
    if(str.equals("TheChosenOne"))
        cls = Class.forName("com.blabla.TheChosenOne");
    else if(str.equals("Rabbit"))
        cls = Class.forName("com.blabla.Rabbit");
    else if(str.equals("Batman"))
        cls = Class.forName("com.heroes.Batman");
    else
        cls = null;

    if(cls != null){
        Query query = mgr.newQuery(MyClass.class);
        for(Object obj : (List<Object>) query.execute()) {
            result.add(((???) obj)); //I need help here!
        }
    }
}
...
return result;

I took the "Class.forName()..." part here .

Any suggestions? Thanks in advance, best regards

What you are trying to do is unnecessary because your list is declared as List<Object> so the cast is not needed.

-- Before Edit --

Not sure I understand what you need, but did you try to use:

Class.cast(object)

This is a method of the java.lang.Class

I think what you are trying to do can be achieved with generics.

For example a method like this:

     public <E> List<E> getList(Class<E> clazz) {
         List<E> result = new ArrayList<E>();
         if(clazz != null){
             Query query = mgr.newQuery(MyClass.class);
             for(E obj : (List<E>)query.execute()) {
                 result.add(obj); 
             }
         }

         return result;
     }

Can be called with:

 getList(TheChosenOne.class)

And it will return a List<TheChosenOne> object

If result is a List<Object> then you don't need a cast at all, simply add(obj) will work fine.

If you need compile time type safety then you will have to pass in the Class object rather than a string containing its name, and use a generic method signature

public <T> List<T> doQuery(Class<T> theClass) {
  List<T> result = new ArrayList<T>();
  try {
    Query query = mgr.newQuery(theClass);
    for(T obj : (List<T>) query.execute()) {
      result.add(obj);
    }
  }
  .... 
  return result;
}

If you go this route, and have the option of modifying the Query class then you might want to consider making that class parameterized

public class Query<E> {
  public List<E> execute() { ... }
}

// and in mgr
public <T> Query<T> newQuery(Class<T> cls)

which would then let you say

    Query<T> query = mgr.newQuery(theClass);
    for(T obj : query.execute()) {
      result.add(obj);

with no casting at all.

我相信cls.cast(obj)就是你要找的。

I think you need to do it in this way: using instance of operator to check the type of the class and then do the type casting

for(Object obj : (List<Object>) query.execute()) {
  if(obj instance of Batman)
    result.add(((Batman) obj));
  else if(obj instance of Cat)
    result.add(((Cat) obj));

  // and so on
  ...
  ...
}

You dont need cast while putting object in the ArrayList,

 result.add(obj); 

If you want you can cast while getting from the list

 cls .cast(result.get(1));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM