Java 当仅将类名作为该类型的字符串给出时转换为未知类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/480894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Casting to Unknown Type When Only Given Class Name as a String of That Type
提问by Paradius
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.
我目前拥有一个对象列表(使用 Java 1.3),假设我想将从 list.get(i) 返回的对象之一转换为我只知道类名称作为字符串的类型。本质上,我如何 Object o = (classname)list.get(i); 其中 className 是 className 的 String 变量。
I thought that I could use ( Class.forName(className) )list.get(i), but I received a syntax error claiming that I forgot a semicolon.
我以为我可以使用 (Class.forName(className))list.get(i),但是我收到一个语法错误,声称我忘记了分号。
Unfortunately, since I am using Java 1.3, I do not have access to the Class.cast(Object) method.
不幸的是,由于我使用的是 Java 1.3,我无法访问 Class.cast(Object) 方法。
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?
在 Java 1.3 中转换为另一种类型时使用的类的名称是什么?是否有一些方法可以使用类名的 String 参数为我提供所需的正确类型?
回答by casperOne
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.
如果您考虑一下,这是有道理的,因为鉴于变量可以是任何类型名称,您应该如何访问各种成员?你不能,除非它们是在所有实例实现的基本类型/接口中定义的,在这种情况下你应该只使用它。
回答by Johannes Schaub - litb
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.
我假设您真的想编写以下内容,而不是Object
在左侧使用。否则,它实际上只是检查列表中的对象是否为正确的类型。
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).
好吧,Java 是静态类型的。你不可能给它一个字符串,它给你相应的静态类型,这样你就可以不用转换了。即使使用泛型 and Class<T>.cast
,转换目标类型也不是由字符串给出,而是由T
在编译时已知的泛型类型参数给出。您必须手动转换为正确的类型,或者继续使用最常见的类型(在您的情况下可能是 Object)。
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(className)
,它会给你一个类型的对象,Class
其中包含有关运行时类型的信息,以便它允许你做
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.
其返回的引用的静态类型是 of Object
。这很重要:被引用对象的动态类型,以及指向该对象的引用的静态类型。对象的动态类型是可以由字符串“控制”的Class.forName
类型(通过使用),但是您在编译时必须处理的引用的静态类型,即(仅举个例子)用于选择相互重载的函数,不能由字符串决定。
回答by ShuggyCoUk
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
如果您要使用反射来获取类的字段/方法就好了
回答by Jonik
The question was answeredalready, but I'd like to add that it seems a bit dubious that you should have a List in which you keep several different kinds of objects (in this case, anyobjects), yet you'd apparently like to invoke operations on them that are specific to each different type...
这个问题已经回答了,但我想补充一点,你应该有一个 List 来保存几种不同类型的对象(在这种情况下,任何对象),这似乎有点可疑,但你显然想要对它们调用特定于每种不同类型的操作......
What's the point of this collection? Don't the instances you keep in it have anythingin common - any common supertype that you could cast them into?
这个收藏有什么意义?您保存在其中的实例是否有任何共同点——您可以将它们转换为任何共同的超类型?
回答by erickson
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.
需要这种情况的一种情况是在遗留系统中实施类型安全时。例如,假设您有一个像 Hibernate 这样的持久性系统,它提供List
来自“finder”方法的原始结果。将此原始List
类型转换为参数化类型将导致未经检查的警告,并且如果 List 包含错误类型的对象,则ClassCastException
可以在某些远相关的代码中在未指定的时间引发。最好使用 OP 建议的机制预先验证列表的内容。
Here's the Java 1.3 version (without generics):
这是 Java 1.3 版本(没有泛型):
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.
在 Java 5 及更高版本中,使用泛型,您可以对Class.cast()
方法执行类似的操作来验证集合的内容,从而证明使用 SuppressWarnings 注释是合理的。在我们的过程中,在没有一些“证据”证明它是安全的情况下抑制警告被列为错误。