简体   繁体   English

传递一个String数组作为参数

[英]passing a String array as argument

A String array can be declared and initialized in the following way: 可以通过以下方式声明和初始化String数组:

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

but for a method which accepts a String array as argument, why can't the same be used there? 但是对于一个接受String数组作为参数的方法,为什么不能在那里使用它?

For example: if in the code below, i replace the call to show() from show(str); 例如:如果在下面的代码中,我将show(str);替换为show()的调用show(str); to show({"A" "B"}); show({"A" "B"}); , it shows complier error. ,它显示编译器错误。 Why? 为什么?

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]);
    }
}

The compiler errors shown are: 显示的编译器错误是:

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

Also using show(new String[] {"A", "B"}); 也使用show(new String[] {"A", "B"}); is allowed. 被允许。 How is new String[]{"A", "B"} different from {"A", "B"} when passing them as method arguments? 当将new String[]{"A", "B"}作为方法参数传递时{"A", "B"} new String[]{"A", "B"}{"A", "B"}有何不同? Thanx in advance! Thanx提前!

The syntax {"A", "B"} (without new String[] in front of it) can only be used as an array initializer expression. 语法{"A", "B"} (前面没有new String[] )只能用作数组初始化表达式。 In all other contexts (including method calls), you need to use the new operator. 在所有其他上下文(包括方法调用)中,您需要使用new运算符。

See the Java Tutorial on Arrays for more info. 有关详细信息,请参阅阵列中Java教程

String[] str = {"A", "B"}; is minified version of String[] str = new String[]{"A", "B"}; String[] str = new String[]{"A", "B"};缩小版本String[] str = new String[]{"A", "B"}; , Compiler doesn't know about plain {"A", "B"} as a string array unless you explicitly mention. 除非你明确提到,否则编译器不会将plain {"A", "B"}知道为字符串数组。

Short Answer 简答

It has everything to do with memory management. 它与内存管理有关。


Long Answer 答案很长

Background : 背景

There is another question about passing arrays as arguments (marked as a duplicate) that is asking about the same behavior but is interested in a deeper 'why'. 关于将数组作为参数传递 (标记为重复)的另一个问题是询问相同的行为,但是对更深层的“为什么”感兴趣。

Other answers have correctly explained the difference between 其他答案正确解释了它们之间的区别

A) 一个)

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

and

B) B)

{"A", "B"} 

when passing them as method arguments. 将它们作为方法参数传递时。

A) constructs an instance of an array on the heap and the expression results in a reference to the instance. A)在堆上构造数组的实例,表达式导致对实例的引用。

B) is the syntax to define an array but that syntax is only valid during the initialization of a local array variable. B)是定义数组的语法,但该语法仅在本地数组变量的初始化期间有效。 This syntax is not an expression that can be evaluated by itself, it expects there to be an array already instantiated but uninitialized where this block is then used as the initializer. 这个语法不是一个可以自己计算的表达式,它期望有一个数组已经实例化但未初始化,然后将该块用作初始化器。

Blame it on Java 归咎于Java

All this has already been mentioned, so what I'd like to answer is the why behind the language design decision that puts this behavior in place. 所有这些都已经提到了,所以我想回答的是语言设计决策背后的原因。

One of the basic tenets of Java is that it manages memory to really minimize the huge problems that introduces when each programmer has to understand all the ins and outs, all the edge cases with dynamic memory management. Java的基本原则之一是它管理内存以真正最小化每个程序员必须了解所有细节时所引入的巨大问题,所有边缘情况都采用动态内存管理。 So, when they designed the language's type system they would have liked to have every variable be a reference type but for efficiency they allowed some basic types that can be passed by value as an argument to a method, where the result is a simple clone of the contents of the variable, these are called primitive types, int, char, etc. All other types require a reference to the heap, which allows for good efficiency in parameter passing, these are called reference types. 因此,当他们设计语言的类型系统时,他们希望将每个变量都作为引用类型,但为了提高效率,它们允许一些基本类型可以通过值作为参数传递给方法,其中结果是一个简单的克隆变量的内容,这些被称为基本类型,int,char等。所有其他类型都需要对堆的引用,这允许参数传递的良好效率,这些被称为引用类型。 Reference types, as the name implies, are actually a reference to memory that has been allocated usually on the heap but can be memory on the stack. 顾名思义,引用类型实际上是对通常在堆上分配但可以是堆栈上的内存的内存的引用。

Array Initializers 数组初始化器

Ok, that's it for the Java Primer, but why is that important? 好的,那就是Java Primer,但为什么这很重要? It's because when you attempt to pass an array as in argument but use the literal syntax, the language expects a reference type but the array initializer construct does not resolve to a reference. 这是因为当您尝试按参数传递数组但使用文字语法时,语言需要引用类型,但数组初始化程序构造不会解析为引用。

Now, the next question might be whether it would have been possible for the compiler to take the initializer syntax and transform it into a properly allocated instance of an array. 现在,下一个问题可能是编译器是否可能采用初始化器语法并将其转换为正确分配的数组实例。 That would be a fair question. 这将是一个公平的问题。 The answer goes back to the the syntax that uses the initializer clause: 答案可以追溯到使用initializer子句的语法:

String[] str = {"A", "B"} String [] str = {“A”,“B”}

If you only have the expression on the right-hand-side of the equals sign, how do you know what type of array should be constructed? 如果你只在等号的右边有表达式,你怎么知道应该构造什么类型的数组? The simple answer is you don't. 简单的答案是你没有。 If we took that same initializer and used it like this 如果我们采用相同的初始化程序并像这样使用它

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

it becomes more clear why this is the case. 更清楚为什么会出现这种情况。 First you might notice the 'new' keyword seems to be missing. 首先你可能会注意到'new'关键字似乎缺失了。 It's not missing but is implicitly being included by the compiler. 它不会丢失,但隐含地被编译器包含在内。 This is because the initializer syntax is a short form of the following code 这是因为初始化器语法是以下代码的简短形式

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

The compiler uses the constructor for the array variable to instantiate each element of the array based on the list provided, So when you try to pass 编译器使用数组变量的构造函数根据提供的列表实例化数组的每个元素,所以当你尝试传递时

{"A", "B"}

the compiler has no information about what type of array should be constructed nor does it know how to construct the individual elements of the array, hence the need to use the form that explicitly allocates memory. 编译器没有关于应该构造什么类型的数组的信息,也不知道如何构造数组的各个元素,因此需要使用显式分配内存的表单。

For the Student of Languages 对于语言学生

This separation between the type of the reference and the type of each element of the array is also what allows the array type to be a parent type of the elements, such as 引用类型和数组中每个元素的类型之间的这种分离也允许数组类型成为元素的父类型,例如

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

and Java's use of a parent class, Object for all classes allows arrays with completely unrelated objects 和Java使用父类,所有类的Object允许数组具有完全不相关的对象

Object[2] myThings = new Object[]();
myThings[0] = new Car();  
myThings[1] = new Guitar(); // unrelated object

When you pass {"A", "B"}, there is no object referencing to it because that array is not yet created in memory and that reference is needed to be passed. 当您传递{“A”,“B”}时,没有对象引用它,因为该数组尚未在内存中创建,并且需要传递该引用。 But we can pass a string like "A" directly [without a reference] to a method accepting String, because String is java's special object for which String pool is maintained. 但是我们可以直接[没有引用]将类似“A”的字符串传递给接受String的方法,因为String是java的特殊对象,为其维护字符串池。 and that is not the case with array which is like simple java object. 这与数组的情况不同,就像简单的java对象一样。

Since String[] str = {"A", "B"}; 由于String[] str = {"A", "B"}; defines that it is an array of strings, {"A", "B"} nowhere says this is an array of string as an array of objects could be defined like that too, thus compiler doesn't know what type of array you are referring to :) 定义它是一个字符串数组, {"A", "B"}没有地方说这是一个字符串数组,因为对象数组也可以这样定义,因此编译器不知道你是什么类型的数组指的是:)

It works if you do it like this 如果你这样做,它的工作原理

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]);
    }
}

because you are actually creating a new array "object". 因为你实际上正在创建一个新的数组“对象”。 The other way, {"A", "B"} doesn't mean anything. 另一方面,{“A”,“B”}并不意味着什么。 {"A", "B"} isn't an array object, so it won't work. {“A”,“B”}不是数组对象,因此不起作用。 The first way works because you are actually specifying that what is being passed to the function is an array object. 第一种方法有效,因为您实际上指定传递给函数的是数组对象。

show({"A" "B"}); show({“A”“B”}); this expression is not passing array object. 这个表达式没有传递数组对象。 Passing array object You have to first declare and intialize the array object then passing array reference into method. 传递数组对象您必须先声明并初始化数组对象,然后将数组引用传递给方法。

String[] str = {"A", "B"}; String [] str = {“A”,“B”}; show(str); 显示(STR);

OR 要么

String[] str = {"A", "B"}; String [] str = {“A”,“B”}; show(new String[]{"A", "B"}); show(new String [] {“A”,“B”});

In the above example, the signature of the show() method guides the compiler that it is expecting a String reference at the time of calling, thus we can pass only a reference variable of type String while calling the show() method. 在上面的例子中,show()方法的签名引导编译器在调用时期望String引用,因此我们只能在调用show()方法时传递String类型的引用变量。 On the other hand {"A","B"} is just an expression not a reference that's why it is giving a compilation error like "Illegal Start of Expression". 另一方面{“A”,“B”}只是一个表达而不是引用,这就是为什么它会给出像“非法表达式开始”这样的编译错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM