反射式检查?

时间:2010-11-13 19:05:39

标签: java reflection types

我想找到一种方法来动态检查字符串是否可以解析为给定类型。 换句话说,

public boolean canBeParsed(String type, String val) {
    // use reflect to check if val can be parsed into type
}

显然,我希望能够检查具有不同值的不同类型。

类型将是以下字符串:Java.lang.Integer

----------另外-------------

所以,例如,如果我调用此函数,

canBeParsed("Java.lang.Integer", "1"); //returns true

canBeParsed("Java.lang.Integer", "HelloWorld"); //returns false

canBeParsed("Java.lang.String", "HelloWorld"); //returns true

canBeParsed("Java.lang.Boolean", "false"); // returns true

canBeParsed("Java.lang.Boolean", "HelloWorld"); //returns false

3 个答案:

答案 0 :(得分:1)

动态类型检查与您要求的不同。通过动态检查,您可以检查对象是否是特定类型的实例(基本上允许使用相同类型或更窄类型),您可以使用instanceof运算符执行此操作。但这涉及对象层次结构,而不是您希望拥有的“可以转换为”概念。您可以尝试使用string instanceof Integer,但这始终是错误的。

在你的情况下,你想检查一个字符串是否存在整数,你应该以不同的方式进行:

try {
  int number = Integer.parseInt(string);
}
catch (NumberFormatException e) {
  System.out.println("String is not an integer string!");
}

否则,您可以为每种类型定义一个正则表达式,并通过它检查字符串包含的内容:

if (string.matches("[1-9][0-9]*"))
  ...

在任何情况下,由于String只是一个字符串类型而没有其他内容,因此RTTI不会帮助您。如果它表示另一种类型的文本版本,那么字符串本身与其他所有类型(int,float,whatever)正交。

如果您可以修改源字符串类型,则可以找到解决方案,在这种情况下,您可以定义例如

class IntString extends String {
  IntString(int i) {
     super(Integer.toString(i));
  }
}

然后你可以检查string instanceof IntString是否只有在字符串使用特定类型构建时才会起作用,例如String s = new IntString(20)

答案 1 :(得分:1)

此方法适用于声明静态valueOf方法的类。没有这个的任何类都将返回false。为了使代码简短,省略了几个例外。

Class<?> cls = Class.forName(type);
//Get a converter method, String to  type
//Requires static method valueOf
Method converter;
try{
converter = cls.getDeclaredMethod("valueOf",new Class[]{String.class});
}catch(NoSuchMethodError ex){
   //No conversion method found
   return false;
}
if(!Modifier.isStatic(converter.getModifiers()){
   //the method has to be static in order to be called by us
   return false;
}
if(!cls.isAssignableFrom(converter.getReturnType())
    //The conversion method has the wrong return type
    return false;
try{
    //try to parse the value
    Object o = converter.invoke(null,new Object[]{value};
    if( o == null)return false;//false if method returned null
    else return true;//success
}catch(Exception ex)
{
    //could not parse value
    return false;
}

valueOf(String)方法存在于包装类Short,Long,Integer,Float,Double,Boolean中,因此它支持这些以及具有此方法的任何其他类。

答案 2 :(得分:0)

您最简单的解决方案可能是switch语句,您希望支持的每种类型都有一个case

public boolean canBeParsed(String type, String val)
{
     switch(type) {
         case "Java.lang.Integer" : return(tryParseInteger(val) != null);
         case ...
}


public static Integer tryParseInteger(String text) {
  try {
    return new Integer(text);
  } catch (NumberFormatException e) {
    return null;
  }
}

在C#中,这会更容易,因为每个数字类型都有一个实际的TryParse()方法,并且没有必要捕获异常来测试它。