Casting to Unknown Type When Only Given Class Name as a String of That Type

20,519

Solution 1

what is the point of casting when all you do is assign the result to object? All you would achieve is an exception if it did not implement the interface/extend or was the class or do nothing if it did.

For that a simple:

  public static boolean IsInstance(object x, String className)
  {
     Class cls = Class.forName(className);
     return cls.isInstance(x);
  }

is sufficient (and cleaner)

If you were to the use reflection to get at the fields/methods of the class that's just fine

Solution 2

No, and you can't do this across most languages.

The reason is that the type to cast to has to be known at compile time, not at runtime (which is what you are trying to do).

If you think about it, it makes sense, because given that the variable could be any type name, how are you supposed to access the various members? You can't, not unless they are defined in a base type/interface that all instances implement, in which case you should just use that.

Solution 3

One scenario where the need for this arises is when enforcing type safety with a legacy system. For example, suppose you have a persistence system like Hibernate that provides a raw List of results from a "finder" method. Casting this raw List to a parameterized type will result in an unchecked warning, and if the List contains an object of the wrong type, a ClassCastException can be raised at an unspecified time in some distantly related code. It may be best to validate the contents of the list up front, using a mechanism like the OP suggests.

Here's the Java 1.3 version (without generics):

private static void checkType(Collection objs, String className) 
  throws ClassNotFoundException
{
  Class clz = Class.forName(className);
  Iterator i = objs.iterator();
  while (i.hasNext()) {
    Object obj = i.next();
    if (!clz.isInstance(obj)) {
      throw new ClassCastException();
    }
  }
}

In Java 5 and later, with generics, you can do something similar with the Class.cast() method to verify the contents of a collection, justifying the use of a SuppressWarnings annotation. In our review process, suppressing a warning without some "proof" that it is safe is filed as a bug.

Solution 4

I assume that you really wanted to write the following, instead of using Object on the left side. Since otherwise, it's really just about checking whether the object in the list is of the right type.

ClassName o = (classname)list.get(i); 

Well, Java is statically typed. It's not possible that you give it a string and it gives you the corresponding static type, so that you can go without casting. Even with generics and Class<T>.cast, the cast destination type is not given by a string, but by the generic type-argument T, which is known at compile-time. You have to manually cast to the right type, or keep using the most common type (may be Object in your case).

If you do Class.forName(className), it gives you back an object of the type Class which contains information about the type at runtime, so that it allows you to do

Class.forName("my.stuff.MyClass").newInstance()

But the cast wants a type - not an object of some type. That is why the compiler told you there is something wrong with that code.

The static type of the reference returned by that is of Object. This is important: The dynamic type of an object that is referenced, and the static type of the reference that points to that object. The dynamic type of the object is what can be "controlled" by a string (by using Class.forName), but the static type of the reference that you have to do with at compile time, and that is (just to give an example) used to select functions that overload each other, can not be determined by a string.

Share:
20,519
Paradius
Author by

Paradius

Updated on July 09, 2022

Comments

  • Paradius
    Paradius almost 2 years

    I currently posses a List of Objects(Using Java 1.3), and let's say that I wanted to cast one of the Objects returned from list.get(i) to a type of which I only know the name of the Class as a String. Essentially, how do I Object o = (classname)list.get(i); where className is a String variable of a className.

    I thought that I could use ( Class.forName(className) )list.get(i), but I received a syntax error claiming that I forgot a semicolon.

    Unfortunately, since I am using Java 1.3, I do not have access to the Class.cast(Object) method.

    What is the name of the class used when casting to another type in Java 1.3? Is there some method that can give me the correct type I need with a String parameter of the class name?