英文:
Different behaviour on Arrays.asList(T...) using ternary
问题
同事在使用`Arrays.asList(T...)`内部的三元运算符时遇到了这种行为。
public static void main(String[] args) throws Exception {
System.out.println(Arrays.asList(new String[]{"2"}));
System.out.println(Arrays.asList(false ? new int[]{2} : new String[]{"2"}));
}
第一个输出打印:`[2]`
第二个输出打印:`[[Ljava.lang.String;@36baf30c]`
所使用的 Java 版本为 Java 8。
第二个输出难道不应该和第一个输出一样吗?
英文:
A colleague came across this behaviour while using ternary operator inside the Arrays.asList(T...)
public static void main(String[] args) throws Exception {
System.out.println(Arrays.asList(new String[]{"2"}));
System.out.println(Arrays.asList(false? new int []{2} :new String[]{"2"}));
}
The first sout prints: [2]
The second one prints: [[Ljava.lang.String;@36baf30c]
The java version used is java 8.
Shouldn't the second sout print the same result as the first?
答案1
得分: 8
Arrays.asList
具有可变参数参数,可以通过两种方式调用:
- 将某种类型的对象数组传递给它,这些对象将成为列表的内容。
- 传递零个或多个对象,它们被放入一个数组中,然后它们成为列表的内容。
你代码的第一个版本
Arrays.asList(new String[]{"2"}))
被解释为在asList
的可变参数参数位置传递了一个字符串数组,因此你得到一个包含数组内容的字符串列表,数组的元素是"2"。
在第二个版本中,表达式的类型
(false ? new int[]{2} : new String[]{"2"})
是Object,因为int[]
和String[]
没有其他共同的基类型,且int数组不能被解释为对象数组。
所以你的asList
调用解析为一个具有一个Object参数的可变参数调用。
这会给你一个包含一个元素的列表,该元素本身就是你的数组。
英文:
Arrays.asList
has varargs parameter, and it can be called in two ways:
- you pass it an array of some kind of objects and those objects become the contents of the list.
- you pass zero or more objects and they are put into an array, and then they become the contents of your list.
The first version of your code
Arrays.asList(new String[]{"2"}))
is interpreted as you passing a String array in place of the varargs argument to asList
, so you get a String list containing the contents of the array, which is the element "2".
In the second version, the type of the expression
(false? new int []{2} :new String[]{"2"})
is Object, since int[]
and String[]
have no other common base type, and an int array cannot be interpreted as an Object array.
So your asList
call resolves to a varargs call with one Object argument.
That gives you a list containing one element, where that element itself is your array.
答案2
得分: 3
Arrays.asList方法的参数是一个可变参数,即T...
,这是一种语法糖,使你可以以以下两种方式之一调用它:
- 你可以使用类型为
T[]
的表达式调用它,在这种情况下,该表达式的结果直接传递到Arrays.asList中。- 这就是你在第一种情况下所做的:参数具有类型
String[]
,因此T
为String
,数组被传递到Arrays.asList中。
- 这就是你在第一种情况下所做的:参数具有类型
- 你可以使用零个或多个类型为
T
的表达式调用它,在这种情况下,这些表达式的结果被捆绑成一个数组,然后将该数组传递到Arrays.asList中。- 这就是你在第二种情况下所做的:参数具有类型
Object
,因此T
为Object
,包含该参数的单元素数组被传递到Arrays.asList中。
- 这就是你在第二种情况下所做的:参数具有类型
这是因为int
不是Object
的子类型,所以int[]
不是Object[]
的子类型。
英文:
The parameter of Arrays.asList is a varargs parameter, T...
, which is syntactic sugar that lets you call it in either of two ways:
- You can call it with an expression of type
T[]
, in which case the result of that expression is passed directly into Arrays.asList.- This is what you're doing in your first case: the argument has type
String[]
, soT
isString
and the array is passed into Arrays.asList.
- This is what you're doing in your first case: the argument has type
- You can call it with zero or more expressions of type
T
, in which case the results of those expressions get bundled up into an array which gets passed into Arrays.asList.- This is what you're doing in your second case: the argument has type
Object
, soT
isObject
and a single-element array containing that argument gets passed into Arrays.asList.
- This is what you're doing in your second case: the argument has type
This is because int
isn't a subtype of Object
, so int[]
isn't a subtype of Object[]
.
答案3
得分: 0
由于 Arrays.asList
接受类型为 T...
的“可变数量”参数,因此它可以以两种方式调用:
- 通过显式数组,例如
Arrays.asList(new String[] {"1", "2"})
- 通过任意数量的数组元素,例如
Arrays.asList("1", "2")
这两种表达式得到的是等价的列表。当该方法仅以一个参数调用时,Java 会根据参数的类型决定是将其视为前一种情况(显式数组)还是后一种情况(作为隐式数组中的单个项):如果它是数组,则直接传递,否则将创建一个包含该单个元素的新数组。
重要的是,由于 Java 具有静态绑定(与动态分派不同),决策是使用参数的编译时类型而不是运行时类型进行的:
- 表达式
new String[] {"1"}
的编译时类型是String[]
,因此它被直接传递为数组,因此您会得到包含一个字符串的列表。 - 然而,表达式
false ? new int[] {2} : new String[] {"2"}
的编译时类型是Object
,因为这是两个操作数类型int[]
和String[]
的最小上界,因此它作为新单元素数组中的元素传递,因此您会得到包含一个包含一个字符串的数组的列表。
英文:
Since Arrays.asList
takes a "variable arity" parameter of type T...
, it can be called in two ways:
- With an explicit array, like
Arrays.asList(new String[] {"1", "2"})
- With any number of array elements, like
Arrays.asList("1", "2")
These two expressions result in equivalent lists. When the method is called with just one argument, Java decides whether to treat it like the former (an explicit array) or the latter (as a singleton in an implicit array) based on the argument's type: if it's an array then it's passed directly, otherwise a new array is created containing that single element.
Importantly, because Java has static binding (which is distinct from dynamic dispatch), the decision is made using the compile-time type of the argument, not its type at runtime:
- The expression
new String[] {"1"}
has compile-time typeString[]
, so it is passed directly as an array, hence you get a list containing one string. - However, the expression
false ? new int[] {2} : new String[] {"2"}
has compile-time typeObject
, since that is the least upper bound of the two operand typesint[]
andString[]
, so it is passed as an element in a new singleton array, hence you get a list containing an array containing one string.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论