不传递参数或为空时的 Java 3 点参数(可变参数)行为 [英] Java 3 dots parameter (varargs) behavior when passed no arguments or null

查看:29
本文介绍了不传递参数或为空时的 Java 3 点参数(可变参数)行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试了这个并从 JAVA 中得到了奇怪的行为,有人可以为我解释一下吗?

I tried this and get weird behavior from JAVA, can someone explain this for me?

boolean testNull(String... string) {
    if(string == null) {
        return true;
    } else {
        System.out.println(string.getClass());
        return false;
    }
}

boolean callTestNull(String s) {
    return testNull(s);
}

然后我有测试用例:

    @Test
    public void test_cases() {
        assertTrue(instance.testNull(null)); // NULL
        assertFalse(instance.testNull()); // NOT NULL
        assertFalse(instance.callTestNull(null)); // NOT NULL
    }

问题是如果我直接用参数null调用testNull(),我会得到true,但是如果调用callTestNull()null,它调用 testNull(),它告诉我参数不是 null,而是空数组.

The question is if I call testNull() directly with parameter null, I will get true back, but if call callTestNull() with null, which calls testNull(), it tells me the parameter is not null, but empty array.

推荐答案

问题是如果我直接用参数null调用testNull(),我会得到true,但是如果用null调用callTestNull(),它调用testNull(),它告诉我参数不是null,而是空数组.

The question is if I call testNull() directly with parameter null, I will get true back, but if call callTestNull() with null, which calls testNull(), it tells me the parameter is not null, but empty array.

是的.如果你用一个编译时类型String参数调用它,编译器知道不能是一个String[],所以它将它包装在一个字符串数组中.所以这个:

Yes. If you call it with an argument with a compile-time type of String, the compiler knows that can't be a String[], so it wraps it within a string array. So this:

String x = null;
testNull(x);

相当于:

String x = null;
testNull(new String[] { x });

此时,(误导性命名的)string 参数将具有非空值 - 相反,它将引用大小为 1 的数组,其唯一元素是空引用.

At this point, the (misleadingly-named) string parameter will have a non-null value - instead, it will refer to an array of size 1 whose sole element is a null reference.

但是,当您在方法调用中直接使用 null 文字时,它可以直接转换为 String[],因此不会执行任何包装.

However, when you use the null literal directly in the method call, that's directly convertible to String[], so no wrapping is performed.

来自 JLS 第 15.12 节.4.2:

如果被调用的方法是一个可变数量的方法 m,那么它必然有 n >0 形式参数.对于某些 T,m 的最终形参必须具有类型 T[],并且 m 必须使用 k ≥ 0 个实参表达式调用.

If the method being invoked is a variable arity method m, it necessarily has n > 0 formal parameters. The final formal parameter of m necessarily has type T[] for some T, and m is necessarily being invoked with k ≥ 0 actual argument expressions.

如果使用 k ≠ n 个实参表达式调用 m,或者,如果使用 k = n 个实参表达式调用 m 并且第 k 个实参表达式的类型与 T[],则参数列表 (e1, ..., en-1, en, ..., ek) 被评估为好像它被写成 (e1, ..., en-1, new |T[]| { en, ..., ek }), 其中 |T[]|表示 T[] 的擦除(第 4.6 节).

If m is being invoked with k ≠ n actual argument expressions, or, if m is being invoked with k = n actual argument expressions and the type of the k'th argument expression is not assignment compatible with T[], then the argument list (e1, ..., en-1, en, ..., ek) is evaluated as if it were written as (e1, ..., en-1, new |T[]| { en, ..., ek }), where |T[]| denotes the erasure (§4.6) of T[].

(强调我的.)

我强调的一点是当参数的编译时类型是 String 而不是 null 类型时,会发生包装.

The bit I've emphasized is why the wrapping only happens when the compile-time type of the argument is String, not the null type.

这篇关于不传递参数或为空时的 Java 3 点参数(可变参数)行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆