我可以將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?
我可以將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?
的char
到int
促進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位值。我不確定爲什麼這是可以接受的參考類型,而不是原始類型,但它可能與原語所需的所有特殊處理有關。
謝謝埃裏克森。我明白了你的觀點。因此,當assign和char []對象指向int引用時,它將避免像Exceptions那樣的ArrayStoreException。 – namalfernandolk
不確定我能爲你提供更多的東西,除了從char []到int []的轉換概念在語言規範中不存在。
在低層次上,它可能與迭代數組本身有關。如果我把一個char []像int []一樣索引到低級別的內存中,它將無法工作。一個4字節的步驟(像int []那樣處理)實際上會在char []中執行2個索引。
你不能以這種方式分配,因爲它是一種類型不匹配。類型int []和char []不兼容。
int[] a = new int[4];
int[] b = a;
兩個a
和b
將引用相同的陣列 - 沒有介入的複製。
如果允許ints=chars
,則應該有一個int[]
變量引用一個16位的數組char
s。諸如ints[0] = 0x12345678
之類的分配是有效的,但結果應該是什麼?
然後,爲什麼我不能指定一個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[]
。
它並不像您期望的那樣工作,因爲(在第一種情況下)該語言隱藏了您的某些類型轉換細節。也就是說,當您將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;
寬元轉換不會失去對數值的 總體規模的信息。 _特殊情況_。見@埃裏克森的答案。 – paislee
你可以使用ByteBuffer來實現類似的'ByteBuffer.asCharBuffer' - >'char []'和'ByteBuffer.asIntBuffer' - >'int []'。如果您使用相同的底層緩衝區,它們共享相同的內存。 – bestsss