Java 使用varargs可以在编译时进行松散的类型检查吗?
在书中,第42项谈到了varargs方法 它说:Java 使用varargs可以在编译时进行松散的类型检查吗?,java,arrays,java-5,Java,Arrays,Java 5,在书中,第42项谈到了varargs方法 它说: ReturnType1 suspect1(Object... args){} <T> ReturnType2 suspect2(T... args){} 由于java1.5及以上版本,由于varargs的引入,上述代码在编译器中很好使用。Arrays.asList(digits)将整个int[]包装到一个对象,以便Arrays.asList(digits)返回数组的一个元素数组List 问题二: 我理解这个示例,它确实是一个丢失类型
ReturnType1 suspect1(Object... args){}
<T> ReturnType2 suspect2(T... args){}
由于java1.5及以上版本,由于varargs
的引入,上述代码在编译器中很好使用。Arrays.asList(digits)
将整个int[]
包装到一个对象,以便Arrays.asList(digits)
返回数组的一个元素数组List
问题二:
我理解这个示例,它确实是一个丢失类型检查的示例,但是将基本int数组(数字
)包装到对象的操作是由数组.asList()
方法执行的,而不是vargars
用法(或者我在这里错了吗?),为什么作者使用这个例子来说明具有这两个签名的所有方法在编译器运行期间都会丢失类型检查?怎样?有什么例子能说服我吗
在上述两种方法信号中,不是Object和t
指定的类型
在那里
有点,但不是真的。运行时将擦除T
。一个简单的例子是Arrays.asList(1,2L,“3”)
,它包含整数
、长
和字符串
。这导致编译时类型T
变成
(这是所有这3个类的超类型)。因此,根据您传递的内容,T
“自适应”在最广泛的情况下成为对象
..将基元int数组(数字)包装到对象的操作是
由Arrays.asList()方法执行,而不是vargars用法(或者
这里怎么了?)
Arrays.asList()
只会将输入数组中的每个元素分配给一个列表。由于varargs的存在,int[]{1,2,3}
将是一个元素(因此T
变成int[]
,因为int
不是一个对象,而Integer{1,2,3}
中T
变成Integer
)。当然,可以编写代码,以便它检查是否有单个输入元素,然后检查它是否是数组,然后将int[]
转换为List
,但这会破坏泛型(int[]
突然变成Integer
),这不是它唯一的问题
ReturnType1 suspect1(Object... args){}
由于所有对象都继承自对象
类,因此编译器执行编译时类型检查是无用的
<T> ReturnType2 suspect2(T... args){}
ReturnType2怀疑2(T…args){}
同样在这里,变量类型T
可能是运行时所需的一切,因此编译器检查类型是无用的
要知道使用vararg是否会丢失类型检查,请使用vararg编写几行代码,并故意将不允许的类型作为vararg传递:您将看到编译器是否失败,或者是否会在运行时引发异常。这是一个类型系统主题
可以将新对象[]{1,2L,“3”}
分配给对象[]
,也可以将新整数[]{1,2,3}
分配给对象[]
,因为数组在Java中是协变的。无法将int[]
分配给对象[]
,但可以将int[]
分配给对象。。。args
以Object[]
为参数的方法将接受Java 1.5之前或之后任何类型的对象数组。但是一种采用对象的方法。。。args
作为参数(仅在Java 1.5之后)也可以接受int[]
那么,您的意思是作者实际上是说,只有当接受原语数组作为参数的方法在切换到varargs
后可以松开类型检查,否则就不能了?@Leem.fin不,原语数组是一个问题,类型擦除只是普通泛型的工作,但是不使用varargs怎么不会产生这个问题呢?作者的观点是,使用varargs可能会带来问题。为什么是varargs的特定问题?这是我主要关心的问题。@Leem.fin,因为varargs是对象[]
顶部的语法糖。通过在方法中使用Object[]params
参数,可以重新创建相同的效果。那里也没有类型安全。当然,请注意,您可以为type参数指定一个界限,因此
将为您指定Number
的上限,而不是Object
。没错。所以,我觉得如果作者试图说这是瓦拉格在上下文中的具体问题,读者会感到困惑。因为没有varargs,例如Object[],T[],这是相同的问题,除非author是指原始参数。是的,但是如果这两个方法显然是以更通用的方式使用的(例如,在泛型类或泛型类中),为什么我需要关心类型检查?我觉得作者想说的是,任何方法,包括那些具有具体类型的方法,只要具有这种签名,都可能导致类型检查松散,这让我感到困惑。我认为编译时的类型检查只能使用已知数据或可以预测的类型来执行。有了那两个签名,他就不能了。如果您没有将类型指定为对象
,而是指定了更具体的类型,那么我真的怀疑编译器是否没有执行类型检查。。。还有,如果有一个vararg。您是否尝试对泛型使用?
通配符?e、 g.returntype1suspect1(我认为我的方法是returntype2suspect2(T[]params)
,作者怎么能说如果我现在改用varargs,我可能会丢失类型检查?在使用varargs之前和之后,我的示例都是泛型T
。这是我不理解的。我认为它们在类型检查方面是相同的。”但是包装原语int数组(数字)的动作对一个对象执行数组。asList()方法“:不确定您的意思…如果没有var args,签名将与int[]
参数不匹配。但是我发现这个问题的说明非常简单
<T> ReturnType2 suspect2(T... args){}