【问题标题】:Java how to check if a string value is a type of given Class<?>Java如何检查字符串值是否是给定Class的类型<?>
【发布时间】:2013-08-08 11:53:00
【问题描述】:

好吧,这是一个复杂的问题,我完全迷路了。

假设您有一个字符串和一个泛型类。像这样。

String string;
Class<?> clazz;

您将如何检查字符串是否表示类可以相等的值。

比如说:

String string = "true";
Class<?> clazz = Boolean.class;

我如何检查字符串“true”实际上是一个布尔值?

这是另一个例子。可以这么说:

String string = "true";
Class<?> clazz = Integer.class;

如何检查字符串“true”是否不是整数?

【问题讨论】:

  • 你想只为 Wrapper 类型做测试吗?
  • 我主要关心原始类型包装器,是的

标签: java string class


【解决方案1】:

鉴于您只希望 Wrapper Types 使用此功能,您可以在此处使用一些反射技巧(为简洁起见,此处忽略了无关代码的异常处理):

String string = "ABC";
Class<?> clazz = Integer.class;

Method method = clazz.getDeclaredMethod("valueOf", String.class);

if (method != null) {
    try {
        Object obj = method.invoke(null, string);       
        System.out.println("Success : " + obj);

    } catch (InvocationTargetException ex) {
        System.out.println("Failure : " + string + " is not of type " + 
                                          clazz.getName());
    }
}

我考虑到这样一个事实,每个包装类都有一个 static valueOf 方法,该方法接受 String 类型的参数,并返回 wrapper 类型的值.如果参数不能转换为相应的包装器类型,则抛出异常。

因此,在上述情况下,如果抛出异常,则string 值不是clazz 类型。

P.S.:请注意,对于Boolean.class,任何不是"true" 的字符串都将被视为false

【讨论】:

    【解决方案2】:

    我假设您正在实施某种规范/协议或类似的东西。

    1. 看规格。
    2. 定义有效输入的语法
    3. 解析该语法。

    这类似于编程语言对文字所做的事情。

    【讨论】:

      【解决方案3】:

      在 javascript 中,您可以 eval() 字符串。在 Java 中你没有这样的方法。您必须为此检查实施自己的启发式方法。

      但是,您可以做的一件事是尝试使用给定的类解析字符串。喜欢:

      Iteger.parseInt(stringValue);
      

      如果解析成功,则字符串可以用作该类型的值。如果失败,那么你会得到一个异常。实施这些检查,然后推导出一些结论。

      【讨论】:

      • 我不能只使用那个方法,因为我不知道这个类是否是一个整数。它是一个泛型类型。
      • 您的问题没有单行解决方案。这就是为什么我说你需要进行一系列检查,然后得出结论。
      • 我不期待单行解决方案。我只是认为必须有一种更好的方法,而不是检查它是否有任何原始类型或我添加的其他类,然后针对我添加的每个类进行检查
      • 您接受了基本上基于我建议的相同想法的答案。仅使用反射并建立在原始类型具有valueOf 方法的事实之上。很好,我确认了。但是,尽量不要重新发明轮子,使用 JSON 或 ProtocolBuffers 来定义消息。与编写自己的启发式解析器相比,容易出错且跨平台的解决方案要少得多。
      【解决方案4】:

      我现在无法测试这个解决方案,但为什么不能这样呢?如果您可以自己枚举所有可能的类,只需在该类上创建一些 switch 语句即可。

      boolean isStringClass (Class clazz, String string) {
      
          try {
              if (Integer.class == clazz) {
                 Integer.valueOf(string);
              } else if (Boolean.class = clazz) {
                 Boolean.valueOf(string);
              } [...etc]
          } catch (Exception e) {
              return false;
          }
      
          return true;
      }
      

      当然,您需要知道所有可能的类,并且您需要知道属于该类的能够解析字符串并返回其类型的方法。对于将是 valueOf 的原始包装器。

      如果您只打算转换包装器,Rohit 的解决方案将是更好的选择。但是,如果您不这样做并且无法将 valueOf 方法添加到这个新类,那么这可能是您唯一的选择。

      【讨论】:

        【解决方案5】:

        我会考虑为此使用 JavaBeans PropertyEditor 机制。

        @Test
        public void testIsOfType() {        
            assertFalse(test("nope", Integer.class));
            assertFalse(test("nope", Boolean.class));
        
            assertTrue(test("1", Integer.class));
            assertTrue(test("true", Boolean.class));
        }
        
        boolean test(String str, Class<?> clazz) {
            PropertyEditor propertyEditor = PropertyEditorManager.findEditor(clazz);
            if (propertyEditor != null) {
                try {           
                    propertyEditor.setAsText(str);
                    return true;
                } catch (Exception ex) {}
            }
            return false;
        }
        

        这避免了显式反射的需要,如果您决定需要测试原始包装器以外的类,您可以使用PropertyEditorManager.registerEditor() 注册一个新编辑器。

        不幸的是,这仍然存在 Rohit 的解决方案存在的问题,即 test("1", Number.class) 将失败。

        【讨论】:

          猜你喜欢
          • 2013-09-04
          • 1970-01-01
          • 2012-04-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-23
          • 2011-06-23
          • 2017-07-03
          相关资源
          最近更新 更多