【问题标题】:Why do I get class cast exception for int.class cast为什么我会得到 int.class cast 的类转换异常
【发布时间】:2012-10-11 07:27:43
【问题描述】:

在下面的程序中,我无法理解为什么 ClassCastException 是来自 int.class 的演员

更新: 我应该指定我知道原始类型是什么。 What I don't understand is why int.class is provided with broken implementation?

  public static void main(String[] args) {
    System.out.println(DataType.INT.getValue(Integer.class));
    System.out.println(DataType.INT.getValue(int.class));//Class cast exception here
}

enum DataType {
    INT {
        @Override
        public <T> T getValue(Class<T> toClass) {
            return toClass.cast(1000);//ClassCastException here for int.class
        }
    };
    public abstract <T> T getValue(Class<T> toClass);

}

【问题讨论】:

  • enum INT&lt;T&gt; 在 java 中是不允许的,所以我试图用其他方式来做。但是正如你所看到的,如果某些人一旦通过int.class,它就会引发ClassCastException,这很容易出错。并且编译器确实限制了INT&lt;int&gt;,但这样就没有了。

标签: java generics


【解决方案1】:

Integerint 值的类包装器,而 int 是原始类型,而不是类。不要混淆原始类型和类,例如在代码中必须使用类时:

List<int> lstInteger; //won't compile!
List<Integer> lstInteger; //compiles fine

更多信息:


int 类型视为原始C/C++ int 类型。知道这一点, int 不是一个类,因此没有任何属性,任何方法,只是保存一个整数值。另一方面,java.lang.Integerint 原始类型的类包装器。这是为了在只能使用对象实例的情况下使用int。一个很好的例子是 Java 中的通用系统,它仅适用于类(如您的代码示例中所建议的那样)。

有关这方面的更深入信息,您可以阅读 Oracle Java 教程:Primitive Data Types

【讨论】:

  • 这两个链接都没有指定cast 应该失败?
  • @LuiggiMendoza。如果你仔细看,他就是OP
【解决方案2】:

好的,在浏览了一些链接并尝试了一些代码后,我发现:-

  • int.class == Integer.TYPE == int
  • int.class != Integer.class

所以,int.class 的值是 Class 对象,表示类型 int

因此,当您使用int.class 调用您的DataType.INT 时,toClass 包含int,您不能在其上调用cast。可能是因为它没有从Object 类扩展。因为,cast 方法内部使用isinstance 来检查调用类型是否为Object 类型。

public T cast(Object obj) {
if (obj != null && !isInstance(obj))
    throw new ClassCastException();
return (T) obj;
}

因此,如果调用cast 的类型不是Object 的实例,当然primitive 类型不是,它将返回false,因此返回ClassCastException

【讨论】:

  • 找到原因将其添加为答案。
  • @AmitD.. 是的,我也刚得到那个链接。但是正如你发布的那样。所以没必要发帖。 :)
  • 我认为您最后的陈述几乎没有改进的余地。事实上,Java 中的所有类都扩展了Object。没有针对 Object 的 instanceof 检查。
  • "所以,int.class 的值为 int。"这根本没有任何意义。 int 是一个类型,而不是一个值。 int.class 的值是一个Class 对象,代表int 类型。
【解决方案3】:

我认为这是因为int.classInteger.class 不同。

更新


我们可以看一下 cast 方法,它的参数是 Object,所以很明显 1000 是自动装箱的,因此该方法的实际参数是 Integer 的实例:

public T cast(Object obj) {
if (obj != null && !isInstance(obj))
    throw new ClassCastException();
return (T) obj;
}

【讨论】:

  • 我知道,但为什么cast 操作失败,因为它最终是一个类对象?
  • 没有这样的int类,它是一个原始类型。
  • @AmitD:因为他们不是同一个班级,他们不共享父子关系。
  • 您似乎将 Java 与其他 OOP 语言混淆了。在 Java 中,int 只是一个原始类型,而不是一个类。 int.anyMethod 将是编译器错误。
  • @LuiggiMendoza:你应该在你的 IDE 上试一试。
【解决方案4】:

当您尝试将一种数据类型的对象转换为另一种数据类型时,Java 会引发类转换异常。这里的 int 不是一个对象,它是一个在运行时被一些本机代码实例化的原语。

【讨论】:

    【解决方案5】:

    发生这种情况是因为Classcast() 操作使用了isInstance() method which returns false for primitive classes

    如果此 Class 对象表示原始类型,则此方法返回 false。

    cast() 方法的代码如下

    public T cast(Object obj) {
    if (obj != null && !isInstance(obj))//It fails here since isInstance returns false
        throw new ClassCastException();
    return (T) obj;
    

    【讨论】:

    • 并且自动装箱导致 obj 成为 Integer 的实例。
    【解决方案6】:

    我认为这是正在发生的事情:

    当您调用return toClass.cast(1000); 时,文字1000 将提升为Integer。促销规则在此提及:Java Language Specification.

    现在,当在 intClass 上调用 cast 方法时,它会检查参数 (1000) 是否属于同一实例,即 int.class,但它会失败,因为它不是。

    另一方面,当您转换为Integer.class 时,它是成功的,因为实例类型确实匹配。

    所以ClassCastException 即将到来是因为Promotion 的文字1000Integer

    【讨论】:

      猜你喜欢
      • 2015-03-17
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 2018-06-22
      • 2012-03-12
      • 1970-01-01
      相关资源
      最近更新 更多