Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 尝试在泛型中使用基元类型时出现奇怪的编译时行为_Java_Arrays_Generics_Primitive_Type Erasure - Fatal编程技术网

Java 尝试在泛型中使用基元类型时出现奇怪的编译时行为

Java 尝试在泛型中使用基元类型时出现奇怪的编译时行为,java,arrays,generics,primitive,type-erasure,Java,Arrays,Generics,Primitive,Type Erasure,我是唯一一个认为编译器让上面的代码编译是绝对疯狂的人吗 例如,在上面的代码中打印c.getSuperclass().getName(),这并不是不合理的,因为我指定了t扩展Number。当然现在getName()将在c==int.class时抛出NullPointerException,因为c.getSuperclass()==null 对我来说,这是一个很好的理由,从一开始就拒绝编译代码 也许是最终的疯狂: public class PrimitiveClassGeneric {

我是唯一一个认为编译器让上面的代码编译是绝对疯狂的人吗

例如,在上面的代码中打印
c.getSuperclass().getName()
,这并不是不合理的,因为我指定了
t扩展Number
。当然现在
getName()
将在
c==int.class
时抛出
NullPointerException
,因为
c.getSuperclass()==null

对我来说,这是一个很好的理由,从一开始就拒绝编译代码


也许是最终的疯狂:

public class PrimitiveClassGeneric {    
    static <T extends Number> T test(Class<T> c) {
        System.out.println(c.getName() + " extends " + c.getSuperclass());
        return (T) null;
    }
    public static void main(String args[]) {
        test(Integer.class);
        // "java.lang.Integer extends class java.lang.Number"

        test(int.class);
        // "int extends null"
    }
}

该代码编译并运行良好。

int.class的类型是
class
,因此
genericArrayNewInstance()
将被推断为返回一个
整数[]
。但是该函数实际上创建了一个
int[]
,因此在返回时会有一个类强制转换异常。基本上,在这种情况下,函数内部对
T[]
的强制转换是不合法的,因为
int[]
不是
T[]
(不能在类型变量中使用原语)。不能通用地处理基元数组类型;因此,您要么让方法只返回类型
对象
,要么为引用类型和基元类型创建单独的方法。

有几点:

  • 在需要时,原语与它们的对象对应物(包装器)连接
  • 基元数组是对象,因此它们不是自动装箱的
  • 泛型不能将原语用作类型参数
  • 对于您的示例,以下是我的假设:

    在3中,自动装箱发生在类型参数上,但不会发生在返回的数组上
    在4中,自动装箱发生在类型参数上,但不发生在方法参数上,因此实际上生成了
    int[]
    ,但需要
    Integer[]

    在类型参数的情况下,自动装箱可能并不完全是自动装箱,但具有相同的思想


    更新:您的第二个示例没有任何错误
    int.class
    是一个
    类,因此编译器没有理由拒绝它。

    我同意原始海报。这太疯狂了。为什么不能将primitive与generic一起使用?这可能不是编译器的问题,而是语言的问题。从泛型中跳过基元类型是错误的

    为此:

    intArray=(int[])Array.newInstance(int.class,0)

    class只是一个类对象。所以可以跳过。“int”是一种类型,所以它不好,因为它显然是原始的。不是说这是创造语言的“最佳”方式,而是要坚持语言


    这太疯狂了,我无法使用泛型为原语的内存(数组)分配创建包装器。如果使用对象,那么对于一个庞大的集合来说,这是非常浪费的。创建Java语言/机器的人的大脑显然有点局限。他们第一次可能会做错,但修复它需要十年时间,而不是做对。

    我可能会错,但我认为从技术上讲,
    int
    没有类,但当你使用
    int.class
    时,编译器框
    int
    Integer
    @matt-b,int.class是一个真正的类。检查javadoc中的Class.isPrimitive。从1.1开始就有了。在拳击之前。Integer.class!=int.class。Integer.TYPE==int.class.“
    int.class
    的类型是
    class
    ”——我认为关键在于这里这些都是好的点,但它们没有回答我的问题。此外,在我的示例中没有自动装箱。如果您在
    genericArrayNewInstance
    中打印
    componentType
    ,它会按原样打印传递的
    .class
    对象。@polygene这就是我所说的-自动装箱不会发生在方法参数上-它已经发生了(当然,它可能不完全是自动装箱,但有类似的想法)添加到类型参数。类型参数不能是原语,因此使用包装器。“您的第二个示例没有任何错误”--但我的通用类型规范要求
    T扩展Number
    ,其中as
    int.class扩展null
    。另请参阅更新到Q。这完全符合我关于自动装箱类型参数的解释,但不适用于自动装箱方法参数。我还是看不出有什么问题。
    public class PrimitiveClassGeneric {    
        static <T extends Number> T test(Class<T> c) {
            System.out.println(c.getName() + " extends " + c.getSuperclass());
            return (T) null;
        }
        public static void main(String args[]) {
            test(Integer.class);
            // "java.lang.Integer extends class java.lang.Number"
    
            test(int.class);
            // "int extends null"
        }
    }
    
        int.class.cast(null);