2013-04-28 51 views
0

我想编写通用代码来解析用户输入并将其与类数组进行比较,然后相应地投射输入。即:从BufferedReader(InputReader)输入解析Integer.class

  1. 对象[] paramTypes = {String.class,String.class,Integer.class}
  2. 对象[] userInput = { “playerName1”, “targetPlayerName”, “5”} // 5是字符串
  3. 用户输入的每个字符串都转换为paramTypes中的相应类。
  4. 最后,将转换的单词放入另一个Object [] castedUserInput中供以后使用。

    for(int i = 0; i<userInput.length; i++) 
        castedUserInput[i] = paramTypes[i].cast(userInput[i]); 
    
问题:

只要paramTypes [i]是Integer.class并且执行投,一个ClassCastException发生。该异常的文档读取:

ClassCastException异常:抛出,表明代码已经试图对象转换子类,它是不是一个实例

所以,既不(对象)“5” (为什么这不起作用?)也不能将“5”转换为Number的子类。

现在我明白,数字和字符串都是对象的子类,但除此之外彼此不相关。我正在安装JDK7来查看的源代码ClassCastException,但我怀疑这对于我只编程了大约一年并且缺乏对什么java编译器和虚拟机正在这里做着。

任何人都可以帮助我吗? PS:当然可以使用几个if子句,然后使用Integer.parseInt(userInput [i]),Long.parseLong(userInput [i])等,但这不可能是最有效的解决方案,对?

+1

没有调用解析功能,是如何知道如何改变一个任意字符串为整数计算机?从编译器的角度来看,它无法区分“4”和“一些随机字符串”。 (虽然显然你不能将后者转换为int) – 2013-04-28 21:32:02

+1

将对象转换为另一种类型决不会改变对象的类型。它所做的只是允许你引用另一个类型的对象,当且仅当它真的具有这种类型。一个字符串是一个字符串,一个CharSequence,一个Serializable,一个COmprable和一个对象,但它不是一个整数。 – 2013-04-28 21:34:55

回答

1

由于输入的类型为String,并且String不能转换为Integer,所以您将得到类别转换异常。您应该查看转换为预期参数类型的输入,而不是转换。为此目的有几个框架,但如果您只有有限数量的可能类型,您可以自己写一些东西。而Integer/Long.parseInt将是一个解决方案。

1

正如你正确地指出的那样,这里的问题是作为字符串的“5”被转换为整数。由于Integer不是String的子类,因此JVM在运行时抛出ClassCasrException。 Integer和String都是Object的子类,因此将String和Integer值转换为Object是安全的(正如在Object数组中存储字符串或整数时所做的那样)。修复

一种方法使用起来会:

for(int i = 0; i<userInput.length; i++) 
    castedUserInput[i] = safeCast(paramTypes[i], userInput[i]); 

其中safeCast()执行转换为您可能使用如果您提及的条款来解析成的int,long等另一种方法,这恕我直言更泛型,将使用反射并调用接受String参数的构造函数。大部分具体的Number类(Byte,Double,Float,Integer,Long,Short)都支持这样的构造函数,所以你应该对Number类很好。对于自定义类,您将需要一个构造函数来接受一个String参数。下面是一个使用反射和依赖于拥有一个构造函数,需要传递的值作为参数解决方案:

public static Object safeCast(Class paramType, Object value) 
     throws NoSuchMethodException, IllegalAccessException, 
     InvocationTargetException, InstantiationException { 
    if (value == null) { 
     return null; 
    } 
    final Class<?> valueClass = value.getClass(); 
    if (paramType.isAssignableFrom(valueClass)) { 
     return value; 
    } 
    final Constructor theConstructor = paramType.getConstructor(valueClass); 
    return theConstructor.newInstance(value); 
}