java學習中的一些疑惑解答
一、java中的枚舉類型:
在實際編程中,往往存在著這樣的“數據集”,它們的數值在程序中是穩定的,而且“數據集”中的元素是有限的。例如星期一到星期日七個數據元素組成了一周的“數據集”,春夏秋冬四個數據元素組成了四季的“數據集”。在java中如何更好的使用這些“數據集”呢?因此枚舉便派上了用場,下面的一段代碼來說明枚舉類型的特點和用法:
public class EnumTest {
public static void main(String[] args) {
Size s=Size.SMALL;
Size t=Size.LARGE;
//s和t引用同一個對象?
System.out.println(s==t); //
//是原始數據類型嗎?
System.out.println(s.getClass().isPrimitive());
//從字符串中轉換
Size u=Size.valueOf("SMALL");
System.out.println(s==u); //true
//列出它的所有值
for(Size value:Size.values()){
System.out.println(value);
}
}
}
enum Size{SMALL,MEDIUM,LARGE};
</code></pre>
從運行結果來看
(1)枚舉類型中的元素不是一個對象,枚舉是一個數據集,它的每個具體值都引用一個特定的對象。相同的值則引用同一個對象。
(2)枚舉類型是一種新的數據類型,并非是原始數據類型
(3)枚舉類型中的元素可以轉換為字符串類型,并且里面的所以元素可以列舉出來
二、反碼,補碼,原碼的理解:
在學習原碼, 反碼和補碼之前, 需要先了解機器數和真值的概念。
1、機器數
一個數在計算機中的二進制表示形式, 叫做這個數的機器數。機器數是帶符號的,在計算機用一個數的最高位存放符號, 正數為0, 負數為1.
比如,十進制中的數 +3 ,計算機字長為8位,轉換成二進制就是00000011。如果是 -3 ,就是 10000011 。
那么,這里的 00000011 和 10000011 就是機器數。
2、真值
因為第一位是符號位,所以機器數的形式值就不等于真正的數值。例如上面的有符號數 10000011,其最高位1代表負,其真正數值是 -3 而不是形式值131(10000011轉換成十進制等于131)。所以,為區別起見,將帶符號位的機器數對應的真正數值稱為機器數的真值。
例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1
對于一個數, 計算機要使用一定的編碼方式進行存儲. 原碼, 反碼, 補碼是機器存儲一個具體數字的編碼方式.
1. 原碼
原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其余位表示值. 比如如果是8位二進制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
第一位是符號位. 因為第一位是符號位, 所以8位二進制數的取值范圍就是:
[1111 1111 , 0111 1111]
即
[-127 , 127]
原碼是人腦最容易理解和計算的表示方式.
2. 反碼
反碼的表示方法是:正數的反碼是其本身,負數的反碼是在其原碼的基礎上, 符號位不變,其余各個位取反.
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
可見如果一個反碼表示的是負數, 人腦無法直觀的看出來它的數值. 通常要將其轉換成原碼再計算.
3. 補碼
補碼的表示方法是:正數的補碼就是其本身,負數的補碼是在其原碼的基礎上, 符號位不變, 其余各位取反, 最后+1. (即在反碼的基礎上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]補
[-1] = [10000001]原 = [11111110]反 = [11111111]補
對于負數, 補碼表示方式也是人腦無法直觀看出其數值的. 通常也需要轉換成原碼在計算其數值.
三、Java中同名變量的屏蔽原則:
每個變量都有一個“有效”的區域(稱為“作用域”),出了這個區域,變量將不再有效,同名的變量在指定的范圍內有自動屏蔽的原則。即局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。下面以一段程序來進行說明:
public class Test {
private static int value = 1;
public static void main(String[] args) {
int value = 2;
System.out.println(value);
輸出結果是:2。顯然可以看出value=1的是全局變量,而value=2的是全局變量。
四、Java中數據類型的轉換規則:
基本數據類型的轉換是指由系統根據轉換規則自動完成,不需要程序員明確地聲明不同數據類型之間的轉換。轉換在編譯器執行,而不是等到運行期再執行。
具體規則:
(1)布爾型和其它基本數據類型之間不能相互轉換;
(2)byte型可以轉換為short、int、long、float和double;
(3)short可轉換為int、long、float和double;
(4)char可轉換為int、long、float和double;
(5)int可轉換為long、float和double;
(6)long可轉換為float和double;
(7)float可轉換為double;
注:(其中除了float類型轉換為double類型為無精度損失,其他類型轉換為double類型都是有精度損失)
也就是說,只能有取值窄的范圍向寬范圍轉換,反之則不行。
五、問題:為什么double類型的數值進行運算得不到“數學上精確”的結果?
答案:這個涉及到二進制與十進制的轉換問題。N進制可以理解為:數值×基數的冪,例如我們熟悉的十進制數123.4=1×102+2×10+3×(10的0次冪)+4×(10的-1次冪);其它進制的也是同理,例如二進制數11.01=1×2+1×(2的0次冪)+0+1×(2的-2次冪)=十進制的3.25。
double類型的數值占用64bit,即64個二進制數,除去最高位表示正負符號的位,在最低位上一定會與實際數據存在誤差(除非實際數據恰好是2的n次方)。
舉個例子來說,比如要用4bit來表示小數3.26,從高到低位依次對應2的1,0,-1,-2次冪,根據最上面的分析,應當在二進制數11.01(對應十進制的3.25)和11.10(對應十進制的3.5)之間選擇。
簡單來說就是我們給出的數值,在大多數情況下需要比64bit更多的位數才能準確表示出來(甚至是需要無窮多位),而double類型的數值只有64bit,后面舍去的位數一定會帶來誤差,無法得到“數學上精確”的結果。
六、Java中輸出的加號連接符的使用:
首先看看下面的代碼輸出結果:
public static void main(String[] args) {
int X=100;
int Y=200;
System.out.println("X+Y="+X+Y);
System.out.println(X+Y+"=X+Y");
}
輸出結果為:

從輸出結果我們可以看出只有與 ” ” 字符串直接相連的后面 “+” 加號才會都被定義成連接符。
System.out.println(“X+Y=”+X+Y); 這條輸出語句打印的內容 ” ” 字符串后面的兩個 “+” 加號都會被定義成連接符,所以是100200而不是300.
System.out.println(X+Y+”=X+Y”); 而這條輸出語句打印的內容前面的X+Y會先運算的,因為前面的 “+” 加號還是運算符,Y后面的+加號才是連接符。只有與 ” ” 字符串直接相連時后面 “+” 加號才會都被定義成連接符。
來自:http://www.58maisui.com/2016/10/08/673/