给定一个 Class<?>, 我能否确定它是否是某个类型的子类?

4
我正在尝试编写一个Java函数,它接受一个Class<?>并返回一个字符串,该字符串代表对应的JavaScript类型。例如,输入/输出如下:
   in              |  out
---------------------------------
 String.class      |  "string"
 int.class         |  "number"
 double.class      |  "number"
 Integer.class     |  "number"
 Date.class        |  "date"    (yes, I know that typeof new Date() === 'object')
 boolean.class     |  "boolean"
 Foo.class         |  "object"

这是我目前的成果,看起来大部分都能正常工作:

String jsType(Class<?> clazz)
{
    if (clazz.equals(String.class) return "string";

    if (clazz.equals(boolean.class) return "boolean";

    try
    {
        clazz.asSubclass(Number.class);
        return "number";
    }
    catch (Exception e){}

    try
    {
        clazz.asSubclass(Date.class);
        return "date";
    }
    catch (Exception e){}

    return "object";
}

然而,它无法正确返回数字原语类型的“number”,例如int.classdouble.class等,尽管对于包装类型Integer.class等,它确实可以正常工作。
  • 原始类型的类字面量有什么特殊之处吗?
  • 是否有一种比为每个我感兴趣的类编写一堆if-else语句更好的方法来编写此函数?
2个回答

4
有两个问题。对于第一个问题,除了明显的表示基本类型之外,原始类型的类文字没有什么特殊之处。"isPrimitive()"方法将为此类类型返回true。您似乎期望原始的“class”类型是Number的子类,但正如您的示例所示,这并不是这种情况。
是否有比一堆if-else语句更好的编写函数的方法?可能没有!虽然我会尝试避免使用异常作为测试,但异常应该保留给真正的异常情况;改用isAssignableFrom(Class<?>) - 虽然我猜这更多是一种风格(也许是效率)的问题。

+1,“isAssignableFrom()”肯定是一种改进。我仍然很好奇为什么“Number.class.isAssignableFrom(int.class)”返回“false” - 这一定是因为“int”是原始类型。 - Matt Ball
@Matt int是一种原始类型,不属于Object类型层次结构的一部分。因此,它不能在任何其他类型(如数字)之上或之下。 - ILMTitan
@ILMTitan: 很好的观点。那你有没有非特定处理这些问题的建议?例如,除了一堆 if-else 语句之外的其他东西。 - Matt Ball
@Matt,你可以通过先确保类型不是boolean,然后仅检查isPrimitive()来合并原始数字类型的检查。对于非原始类型,如果你真的想要,可以使用哈希映射将Java类名映射到JavaScript类型。但我认为你无法完全避免if-then-else。 - davmac

1
这里有一种方法,首先对类进行规范化,简化了jsType方法:
Class<?> normalise(Class<?> cls) {
    if (Number.class.isAssignableFrom(cls) ||
        cls == int.class || cls == long.class || 
        cls == double.class || cls == float.class) {
        return Number.class;
    } else if (cls == Boolean.class || cls == boolean.class) {
        return Boolean.class;
    } else if (Date.class.isAssignableFrom(cls)) {
        return Date.class;
    } else {
        return cls;
    }
}

String jsType(Class<?> cls) {
    Class<?> normalised = normalise(cls);
    if (normalised == Number.class) {
        return "number";
    } else if (normalised == Boolean.class) {
        return "boolean";
    } else if (normalised == Date.class) {
        return "date";
    } else if (normalised == String.class) {
        return "string";
    } else {
        return "object";
    }
}

这看起来很不错。你确定我可以在类字面值上使用==而不是.equals()吗? - Matt Ball
当然,你也可以将这两种方法结合起来。这可能是最简单的方法。 - harto
1
你可以放心地使用“==”来比较类的实例。规范中规定,每个类加载器只有一个给定类对象的实例。(而且它也不会覆盖默认的equals()方法,所以这就是你能得到的全部内容了。) - Affe
@Affe:感谢您的澄清。我不习惯使用类字面量(它们是Class的实例吗?)。 - Matt Ball
是的,Date.class == new Date().getClass() 这个语句是正确的,简单来说 :) - Affe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接