在使用三元运算符时,Arrays.asList(T…) 的行为不同。

huangapple go评论76阅读模式
英文:

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具有可变参数参数,可以通过两种方式调用:

  1. 将某种类型的对象数组传递给它,这些对象将成为列表的内容。
  2. 传递零个或多个对象,它们被放入一个数组中,然后它们成为列表的内容。

你代码的第一个版本

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:

  1. you pass it an array of some kind of objects and those objects become the contents of the list.
  2. 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[],因此TString,数组被传递到Arrays.asList中。
  • 你可以使用零个或多个类型为T的表达式调用它,在这种情况下,这些表达式的结果被捆绑成一个数组,然后将该数组传递到Arrays.asList中。
    • 这就是你在第二种情况下所做的:参数具有类型Object,因此TObject,包含该参数的单元素数组被传递到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[], so T is String and the array is passed into Arrays.asList.
  • 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, so T is Object and a single-element array containing that argument gets passed into Arrays.asList.

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 type String[], 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 type Object, since that is the least upper bound of the two operand types int[] and String[], so it is passed as an element in a new singleton array, hence you get a list containing an array containing one string.

huangapple
  • 本文由 发表于 2020年9月12日 04:35:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/63853993.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定