Java 在另一个可变参数方法中调用可变参数方法时,可变参数未检测到
Java varags not detect when call vararg method inside another vararg method
我已经实施了 Java 方法来解决 IN 和 OR 条件。
下面是我的代码。
public static <T> boolean in(T parameter, T... values) {
if (null != values) {
System.out.println("IN values size.. " + values.length);
return Arrays.asList(values).contains(parameter);
}
return false;
}
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
return in(true, values);
}
public static void main(String[] args) {
System.out.println(or(false, true, false));
}
输出为:
OR values size.. 3
IN values size.. 1
false
但我期待以下输出:
OR values size.. 3
IN values size.. 3
true
我不明白为什么 in
方法中的可变参数大小为 1。
方法中
in(T parameter, T... values) //in(true, values); // values is T
当您传递一个布尔数组 values
时,整个数组被视为一个元素 T
这就是显示它的原因 1
.
您传递的是布尔数组,接收类型是T
,其中每个元素都被视为一个数组。
你可以在方法中打印里面的值,看看结果是什么。你会看到一个数组对象。不是单个布尔元素。
当您输入 or
时,boolean... values
参数将转换为 boolean
的数组。然后,当你调用 in(true, values)
时,in
的第二个参数实际上是原始类型的数组 boolean
(因此是单个值)。实际问题是 Java 不会自动装箱基本类型数组。
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
// here values is an array of the primitive boolean
return in(true, values);
}
public static void main(String[] args) {
System.out.println(or(false, true, false));
}
您可以通过将 boolean
装箱到 Boolean
对象来解决这个问题,如下所示:
public static <T> boolean in(T parameter, T... values) {
if (null != values) {
System.out.println("IN values size.. " + values.length);
return Arrays.asList(values).contains(parameter);
}
return false;
}
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
Boolean[] boxedValues = new Boolean[values.length];
for (int i = 0; i < values.length; i++) {
boxedValues[i] = values[i];
}
return in(true, boxedValues);
}
public static void main(String[] args) {
System.out.println(or(false, true, false));
}
请注意,从 Java 7 开始,此代码将发出警告,您可以使用 @SafeVarargs
注释将其禁用。
我使用静态工具来处理这种奇怪的边缘情况。
/**
* Can rebox a boxed primitive array into its Object form.
*
* Generally I HATE using instanceof because using it is usually an indication that your hierarchy is completely wrong.
*
* Reboxing - however - is an area I am ok using it.
*
* Generally, if a primitive array is passed to a varargs it is wrapped up as the first and only component of an Object[].
*
* E.g.
*
* public void f(T... t) {}; f(new int[]{1,2});
*
* actually ends up calling f with t an Object[1] and t[0] the int[].
*
* This unwraps it and returns the correct reboxed version.
*
* In the above example it will return an Integer[].
*
* Any other array types will be returned unchanged.
*
* @author OldCurmudgeon
*/
public static class Rebox {
public static <T> T[] rebox(T[] it) {
// Default to return it unchanged.
T[] result = it;
// Special case length 1 and it[0] is primitive array.
if (it.length == 1 && it[0].getClass().isArray()) {
// Which primitive array is it?
if (it[0] instanceof int[]) {
result = rebox((int[]) it[0]);
} else if (it[0] instanceof long[]) {
result = rebox((long[]) it[0]);
} else if (it[0] instanceof float[]) {
result = rebox((float[]) it[0]);
} else if (it[0] instanceof double[]) {
result = rebox((double[]) it[0]);
} else if (it[0] instanceof char[]) {
result = rebox((char[]) it[0]);
} else if (it[0] instanceof byte[]) {
result = rebox((byte[]) it[0]);
} else if (it[0] instanceof short[]) {
result = rebox((short[]) it[0]);
} else if (it[0] instanceof boolean[]) {
result = rebox((boolean[]) it[0]);
}
}
return result;
}
// Rebox each one separately.
private static <T> T[] rebox(int[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Integer.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(long[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Long.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(float[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Float.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(double[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Double.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(char[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Character.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(byte[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Byte.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(short[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Short.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(boolean[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Boolean.valueOf(it[i]);
}
return boxed;
}
// Trick to make a T[] of any length.
// Do not pass any parameter for `dummy`.
// public because this is potentially re-useable.
public static <T> T[] makeTArray(int length, T... dummy) {
return Arrays.copyOf(dummy, length);
}
}
public static <T> boolean in(T parameter, T... values) {
if (null != values) {
System.out.println("IN values size.. " + values.length);
return Arrays.asList(values).contains(parameter);
}
return false;
}
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
return in(true, Rebox.rebox(values));
}
public void test() {
System.out.println(or(false, true, false));
}
这会打印:
OR values size.. 3
IN values size.. 3
true
如你所愿。
我已经实施了 Java 方法来解决 IN 和 OR 条件。
下面是我的代码。
public static <T> boolean in(T parameter, T... values) {
if (null != values) {
System.out.println("IN values size.. " + values.length);
return Arrays.asList(values).contains(parameter);
}
return false;
}
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
return in(true, values);
}
public static void main(String[] args) {
System.out.println(or(false, true, false));
}
输出为:
OR values size.. 3
IN values size.. 1
false
但我期待以下输出:
OR values size.. 3
IN values size.. 3
true
我不明白为什么 in
方法中的可变参数大小为 1。
方法中
in(T parameter, T... values) //in(true, values); // values is T
当您传递一个布尔数组 values
时,整个数组被视为一个元素 T
这就是显示它的原因 1
.
您传递的是布尔数组,接收类型是T
,其中每个元素都被视为一个数组。
你可以在方法中打印里面的值,看看结果是什么。你会看到一个数组对象。不是单个布尔元素。
当您输入 or
时,boolean... values
参数将转换为 boolean
的数组。然后,当你调用 in(true, values)
时,in
的第二个参数实际上是原始类型的数组 boolean
(因此是单个值)。实际问题是 Java 不会自动装箱基本类型数组。
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
// here values is an array of the primitive boolean
return in(true, values);
}
public static void main(String[] args) {
System.out.println(or(false, true, false));
}
您可以通过将 boolean
装箱到 Boolean
对象来解决这个问题,如下所示:
public static <T> boolean in(T parameter, T... values) {
if (null != values) {
System.out.println("IN values size.. " + values.length);
return Arrays.asList(values).contains(parameter);
}
return false;
}
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
Boolean[] boxedValues = new Boolean[values.length];
for (int i = 0; i < values.length; i++) {
boxedValues[i] = values[i];
}
return in(true, boxedValues);
}
public static void main(String[] args) {
System.out.println(or(false, true, false));
}
请注意,从 Java 7 开始,此代码将发出警告,您可以使用 @SafeVarargs
注释将其禁用。
我使用静态工具来处理这种奇怪的边缘情况。
/**
* Can rebox a boxed primitive array into its Object form.
*
* Generally I HATE using instanceof because using it is usually an indication that your hierarchy is completely wrong.
*
* Reboxing - however - is an area I am ok using it.
*
* Generally, if a primitive array is passed to a varargs it is wrapped up as the first and only component of an Object[].
*
* E.g.
*
* public void f(T... t) {}; f(new int[]{1,2});
*
* actually ends up calling f with t an Object[1] and t[0] the int[].
*
* This unwraps it and returns the correct reboxed version.
*
* In the above example it will return an Integer[].
*
* Any other array types will be returned unchanged.
*
* @author OldCurmudgeon
*/
public static class Rebox {
public static <T> T[] rebox(T[] it) {
// Default to return it unchanged.
T[] result = it;
// Special case length 1 and it[0] is primitive array.
if (it.length == 1 && it[0].getClass().isArray()) {
// Which primitive array is it?
if (it[0] instanceof int[]) {
result = rebox((int[]) it[0]);
} else if (it[0] instanceof long[]) {
result = rebox((long[]) it[0]);
} else if (it[0] instanceof float[]) {
result = rebox((float[]) it[0]);
} else if (it[0] instanceof double[]) {
result = rebox((double[]) it[0]);
} else if (it[0] instanceof char[]) {
result = rebox((char[]) it[0]);
} else if (it[0] instanceof byte[]) {
result = rebox((byte[]) it[0]);
} else if (it[0] instanceof short[]) {
result = rebox((short[]) it[0]);
} else if (it[0] instanceof boolean[]) {
result = rebox((boolean[]) it[0]);
}
}
return result;
}
// Rebox each one separately.
private static <T> T[] rebox(int[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Integer.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(long[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Long.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(float[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Float.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(double[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Double.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(char[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Character.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(byte[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Byte.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(short[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Short.valueOf(it[i]);
}
return boxed;
}
private static <T> T[] rebox(boolean[] it) {
T[] boxed = makeTArray(it.length);
for (int i = 0; i < it.length; i++) {
boxed[i] = (T) Boolean.valueOf(it[i]);
}
return boxed;
}
// Trick to make a T[] of any length.
// Do not pass any parameter for `dummy`.
// public because this is potentially re-useable.
public static <T> T[] makeTArray(int length, T... dummy) {
return Arrays.copyOf(dummy, length);
}
}
public static <T> boolean in(T parameter, T... values) {
if (null != values) {
System.out.println("IN values size.. " + values.length);
return Arrays.asList(values).contains(parameter);
}
return false;
}
public static boolean or(boolean... values) {
System.out.println("OR values size.. " + values.length);
return in(true, Rebox.rebox(values));
}
public void test() {
System.out.println(or(false, true, false));
}
这会打印:
OR values size.. 3
IN values size.. 3
true
如你所愿。