2012-01-26 76 views
4

我可以將char指定給int,如下所示。無法從char []轉換爲int []

char c = 'a'; 
int a = 0; 
    a = c; 

那麼,爲什麼我不能指定一個字符[]爲int []

int[] ints= new int[4]; 
char[] chars= new char[4]; 
ints = chars; // Cannot convert from char[] to int[] ?? But why? 
+0

寬元轉換不會失去對數值的 總體規模的信息。 _特殊情況_。見@埃裏克森的答案。 – paislee

+0

你可以使用ByteBuffer來實現類似的'ByteBuffer.asCharBuffer' - >'char []'和'ByteBuffer.asIntBuffer' - >'int []'。如果您使用相同的底層緩衝區,它們共享相同的內存。 – bestsss

回答

4

charint促進is a special provision for primitive types.

關於陣列中,Java Language Specification says this:

如果數組變量v具有類型A [],其中A是一個引用類型,然後 -v可以保持一個參考提供給任何數組類型B []的實例,只要提供 B就可以分配給A.這可能會導致運行時異常在以後的分配上執行 ;參見§10.10進行討論。

這隻適用於「如果A是參考類型」。儘管char可以分配給int,但是該規則不適用,因爲它不適用於基元類型。

因此,沒有任何特殊的規定來分配不兼容的類型,分配失敗。

如果允許,你會介紹ArrayStoreException的可能性調高商店基本數組(就像您目前有引用類型的數組):

ints[0] = Integer.MAX_VALUE; /* Exception! */ 

這是因爲ints是別名爲char[],無法容納32位值。我不確定爲什麼這是可以接受的參考類型,而不是原始類型,但它可能與原語所需的所有特殊處理有關。

+0

謝謝埃裏克森。我明白了你的觀點。因此,當assign和char []對象指向int引用時,它將避免像Exceptions那樣的ArrayStoreException。 – namalfernandolk

2

不確定我能爲你提供更多的東西,除了從char []到int []的轉換概念在語言規範中不存在。

在低層次上,它可能與迭代數組本身有關。如果我把一個char []像int []一樣索引到低級別的內存中,它將無法工作。一個4字節的步驟(像int []那樣處理)實際上會在char []中執行2個索引。

0

你不能以這種方式分配,因爲它是一種類型不匹配。類型int []和char []不兼容。

1
int[] a = new int[4]; 
int[] b = a; 

兩個ab將引用相同的陣列 - 沒有介入的複製。

如果允許ints=chars,則應該有一個int[]變量引用一個16位的數組char s。諸如ints[0] = 0x12345678之類的分配是有效的,但結果應該是什麼?

2

然後,爲什麼我不能指定一個char [] int []?

第一個答案是因爲Java語言規範禁止這樣做。關鍵部分是4.10.3.,它指定了數組類型的子類型規則。規則意味着沒有原始數組類型是另一個(不同的)原始數組類型的子類型。這樣做的一個後果是任務被禁止。

第二個答案(以及JLS禁止它的原因)是,如果允許,它會打破類型系統。考慮這個例子:

int[] ints= new int[4]; 
char[] chars= new char[4]; 
ints = chars; 

該賦值是一個引用賦值。這意味着ints現在將指向上一行由new char[4]創建的數組對象。 (它不是相當於一個循環,chars「元素的值分配給ints。)

現在讓我們來添加的方法:

public void paranoidIncrement(int[] ints) { 
    for (int i = 0; i < ints.length; i++) { 
     int tmp = int[i]; 
     ints[i] = ints[i] + 1; 
     assert tmp + 1 == ints[i]; 
    } 
} 

,並允許與前面的代碼結合起來:

int[] ints= new int[4]; 
char[] chars= new char[4]; 
ints = chars;    // assume this is legal ... 
paranoidIncrement(ints); 

那麼這是什麼意思?那麼paranoidIncrement會將參數(它實際上是char[])視爲int[]。但是當我們做ints[i] = ints[i] + 1;會發生什麼?如果實際的陣列的單元格實際上是char s,那麼JVM 已將截斷值以使它們合適或引發異常。

  • 如果它截斷該值,那麼assert語句將失敗。這是非常直觀的,它只是簡單的破碎。

  • 如果它拋出一個異常,那麼我們突然收到了一整類新的錯誤,它們是在編譯時檢測到的(在JLS規則下)。

的方式,Java的避免了破碎是說,你不能分配char[]int[]

0

它並不像您期望的那樣工作,因爲(在第一種情況下)該語言隱藏了您的某些類型轉換細節。也就是說,當您將char分配給int時,有時將其稱爲隱式轉換。這相當於這樣做:

char c = 'a'; 
int a = 0; 
    a = (int) c; 

...這將很好地工作,但語言不強迫你每次寫(int)演員。

在第二個示例中,演員表不起作用。如果試圖在添加明確演員,你會得到一個錯誤,如:

Foo.java:9: inconvertible types 
found : char[] 
required: int[] 
     int[] ints = (int[]) chars;