[英]passing a String array as argument
可以通過以下方式聲明和初始化String數組:
String[] str = {"A", "B"};
但是對於一個接受String數組作為參數的方法,為什么不能在那里使用它?
例如:如果在下面的代碼中,我將show(str);
替換為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"}
new String[]{"A", "B"}
與{"A", "B"}
有何不同? Thanx提前!
String[] str = {"A", "B"};
是String[] str = new String[]{"A", "B"};
縮小版本String[] str = new String[]{"A", "B"};
除非你明確提到,否則編譯器不會將plain {"A", "B"}
知道為字符串數組。
它與內存管理有關。
背景 :
關於將數組作為參數傳遞 (標記為重復)的另一個問題是詢問相同的行為,但是對更深層的“為什么”感興趣。
其他答案正確解釋了它們之間的區別
一個)
new String[]{"A", "B"}
和
B)
{"A", "B"}
將它們作為方法參數傳遞時。
A)在堆上構造數組的實例,表達式導致對實例的引用。
B)是定義數組的語法,但該語法僅在本地數組變量的初始化期間有效。 這個語法不是一個可以自己計算的表達式,它期望有一個數組已經實例化但未初始化,然后將該塊用作初始化器。
所有這些都已經提到了,所以我想回答的是語言設計決策背后的原因。
Java的基本原則之一是它管理內存以真正最小化每個程序員必須了解所有細節時所引入的巨大問題,所有邊緣情況都采用動態內存管理。 因此,當他們設計語言的類型系統時,他們希望將每個變量都作為引用類型,但為了提高效率,它們允許一些基本類型可以通過值作為參數傳遞給方法,其中結果是一個簡單的克隆變量的內容,這些被稱為基本類型,int,char等。所有其他類型都需要對堆的引用,這允許參數傳遞的良好效率,這些被稱為引用類型。 顧名思義,引用類型實際上是對通常在堆上分配但可以是堆棧上的內存的內存的引用。
好的,那就是Java Primer,但為什么這很重要? 這是因為當您嘗試按參數傳遞數組但使用文字語法時,語言需要引用類型,但數組初始化程序構造不會解析為引用。
現在,下一個問題可能是編譯器是否可能采用初始化器語法並將其轉換為正確分配的數組實例。 這將是一個公平的問題。 答案可以追溯到使用initializer子句的語法:
String [] str = {“A”,“B”}
如果你只在等號的右邊有表達式,你怎么知道應該構造什么類型的數組? 簡單的答案是你沒有。 如果我們采用相同的初始化程序並像這樣使用它
Circle[] cir = {"A", "B"}
更清楚為什么會出現這種情況。 首先你可能會注意到'new'關鍵字似乎缺失了。 它不會丟失,但隱含地被編譯器包含在內。 這是因為初始化器語法是以下代碼的簡短形式
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
當您傳遞{“A”,“B”}時,沒有對象引用它,因為該數組尚未在內存中創建,並且需要傳遞該引用。 但是我們可以直接[沒有引用]將類似“A”的字符串傳遞給接受String的方法,因為String是java的特殊對象,為其維護字符串池。 這與數組的情況不同,就像簡單的java對象一樣。
由於String[] str = {"A", "B"};
定義它是一個字符串數組, {"A", "B"}
沒有地方說這是一個字符串數組,因為對象數組也可以這樣定義,因此編譯器不知道你是什么類型的數組指的是:)
如果你這樣做,它的工作原理
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”}不是數組對象,因此不起作用。 第一種方法有效,因為您實際上指定傳遞給函數的是數組對象。
show({“A”“B”}); 這個表達式沒有傳遞數組對象。 傳遞數組對象您必須先聲明並初始化數組對象,然后將數組引用傳遞給方法。
String [] str = {“A”,“B”}; 顯示(STR);
要么
String [] str = {“A”,“B”}; show(new String [] {“A”,“B”});
在上面的例子中,show()方法的簽名引導編譯器在調用時期望String引用,因此我們只能在調用show()方法時傳遞String類型的引用變量。 另一方面{“A”,“B”}只是一個表達而不是引用,這就是為什么它會給出像“非法表達式開始”這樣的編譯錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.