14

可以通过以下方式声明和初始化 String 数组:

String[] str = {"A", "B"};

但是对于接受字符串数组作为参数的方法,为什么不能在那里使用相同的方法?

例如:如果在下面的代码中,我将对 show() 的调用替换show(str);show({"A" "B"});,它会显示编译器错误。为什么?

public class StringArray {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String[] str = {"A", "B"};
        show(str);
    }
    static void show(String[] s) {
        System.out.println(s[0] + s[1]);
    }
}

显示的编译器错误是:

StringArray.java:9: illegal start of expression
                show({"A", "B"});
                     ^
StringArray.java:9: ';' expected
                show({"A", "B"});
                      ^
StringArray.java:9: illegal start of expression
                show({"A", "B"});
                         ^
StringArray.java:9: ';' expected
                show({"A", "B"});
                          ^
StringArray.java:9: illegal start of type
                show({"A", "B"});
                               ^
StringArray.java:11: class, interface, or enum expected
        static void show(String[] s) {
               ^
StringArray.java:13: class, interface, or enum expected
        }
        ^
7 errors

show(new String[] {"A", "B"});允许使用。与将它们作为方法参数传递时有何不同new String[]{"A", "B"}{"A", "B"}提前谢谢!

4

8 回答 8

12

语法{"A", "B"}new String[]前面没有)只能用作数组初始化表达式。在所有其他上下文中(包括方法调用),您需要使用new运算符。

有关更多信息,请参阅Java 数组教程。

于 2012-07-18T05:56:14.083 回答
6

String[] str = {"A", "B"};是 的缩小版本String[] str = new String[]{"A", "B"};,除非您明确提及,否则编译器不知道 plain{"A", "B"}作为字符串数组。

于 2012-07-18T05:57:00.687 回答
2

简答

它与内存管理有关。


长答案

背景

还有另一个关于将数组作为参数传递(标记为重复)的问题,它询问相同的行为,但对更深层次的“为什么”感兴趣。

其他答案已经正确解释了

一种)

new String[]{"A", "B"} 

二)

{"A", "B"} 

将它们作为方法参数传递时。

A) 在堆上构造一个数组的实例,并且表达式导致对该实例的引用。

B) 是定义数组的语法,但该语法仅在局部数组变量的初始化期间有效。此语法不是一个可以自行评估的表达式,它期望有一个已经实例化但未初始化的数组,然后将此块用作初始化程序。

归咎于Java

所有这一切都已经提到过,所以我想回答的是为什么语言设计决策背后会出现这种行为。

Java 的基本原则之一是它管理内存以真正最小化当每个程序员必须了解所有细节和动态内存管理的所有边缘情况时引入的巨大问题。因此,当他们设计语言的类型系统时,他们希望每个变量都是引用类型,但为了提高效率,他们允许一些基本类型可以通过值作为参数传递给方法,结果是一个简单的克隆变量的内容,这些被称为原始类型、int、char 等。所有其他类型都需要对堆的引用,这样可以提高参数传递的效率,这些被称为引用类型。顾名思义,引用类型实际上是对通常在堆上分配的内存的引用,但也可以是堆栈上的内存。

数组初始化器

好的,这就是 Java Primer 的内容,但为什么这很重要?这是因为当您尝试将数组作为参数传递但使用文字语法时,该语言需要引用类型,但数组初始值设定项构造不会解析为引用。

现在,下一个问题可能是编译器是否有可能采用初始化语法并将其转换为正确分配的数组实例。那将是一个公平的问题。答案可以追溯到使用初始化子句的语法:

字符串[] str = {"A", "B"}

如果你只有等号右边的表达式,你怎么知道应该构造什么类型的数组?简单的答案是你没有。如果我们采用相同的初始化程序并像这样使用它

Circle[] cir = {"A", "B"}

为什么会这样变得更清楚了。首先,您可能会注意到似乎缺少“新”关键字。它并没有丢失,而是被编译器隐式包含在内。这是因为初始化器语法是以下代码的缩写形式

Circle[2] cir = new Circle[]();
cir[0] = new Circle("A");
cir[1] = new Circle("B");

编译器使用数组变量的构造函数根据提供的列表实例化数组的每个元素,所以当你尝试传递

{"A", "B"}

编译器没有关于应该构造什么类型的数组的信息,也不知道如何构造数组的各个元素,因此需要使用显式分配内存的形式。

对于语言学生

引用的类型和数组每个元素的类型之间的这种分离也是允许数组类型成为元素的父类型的原因,例如

Circle[2] shapes = new Circle[]();
shapes[0] = new Circle();  // parent
shapes[1] = new Ellipse(); // child of Circle 

和 Java 对父类的使用,Object对于所有类都允许具有完全不相关对象的数组

Object[2] myThings = new Object[]();
myThings[0] = new Car();  
myThings[1] = new Guitar(); // unrelated object
于 2017-03-24T14:12:30.617 回答
1

当您传递 {"A", "B"} 时,没有对象引用它,因为该数组尚未在内存中创建,需要传递该引用。但是我们可以直接[没有引用]将像“A”这样的字符串传递给接受字符串的方法,因为字符串是java的特殊对象,为它维护字符串池。而数组不是这种情况,它就像简单的 java 对象。

于 2012-07-18T06:02:46.703 回答
0

由于String[] str = {"A", "B"};定义它是一个字符串数组,所以{"A", "B"}没有地方说这是一个字符串数组,因为对象数组也可以这样定义,因此编译器不知道您指的是什么类型的数组:)

于 2012-07-18T05:57:14.143 回答
0

如果你这样做,它会起作用

public class StringArray 
{

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        show(new String[]{"A", "B"});
    }
    static void show(String[] s)
    {
        System.out.println(s[0] + s[1]);
    }
}

因为您实际上是在创建一个新的数组“对象”。另一方面,{"A", "B"} 没有任何意义。{"A", "B"} 不是数组对象,所以它不起作用。第一种方法有效,因为您实际上指定传递给函数的是数组对象。

于 2012-07-18T05:59:03.323 回答
0

显示({“A”“B”});此表达式未传递数组对象。传递数组对象您必须首先声明和初始化数组对象,然后将数组引用传递给方法。

字符串[] str = {"A", "B"}; 显示(str);

或者

字符串[] str = {"A", "B"}; 显示(新字符串 []{“A”,“B”});

于 2012-07-18T07:30:55.620 回答
0

在上面的例子中,show() 方法的签名告诉编译器在调用时它期望一个 String 引用,因此我们在调用 show() 方法时只能传递一个 String 类型的引用变量。另一方面 {"A","B"} 只是一个表达式而不是一个引用,这就是为什么它会给出一个编译错误,比如“Illegal Start of Expression”。

于 2012-07-18T12:27:13.353 回答