上次談到了Java的基本數據類型,今天接著聊Java的變數、運算符。 一、變數 1、變數的分類 變數分為成員變數、局部變數和常量,其中成員變數又分為實例變數、類變數。 2、變數的定義 語法:變數類型(可以是基本類型,也可以是其他) 變數名 = 變數值 英文;結尾。 2.1 可以單次聲明一個變數,也可 ...
上次談到了Java的基本數據類型,今天接著聊Java的變數、運算符。
一、變數
1、變數的分類
變數分為成員變數、局部變數和常量,其中成員變數又分為實例變數、類變數。
2、變數的定義
語法:變數類型(可以是基本類型,也可以是其他) 變數名 = 變數值 英文;結尾。
2.1 可以單次聲明一個變數,也可以單次聲明多個變數。
2.2 不能以數字、運算符、特殊字元(下劃線、美元符號$除外)開頭。
2.3 下劃線 _ 可以作為開頭,但是不建議這樣命名。
2.4 可以使用中文命名,但是不建議這樣做。
2.5 不能使用現有Java關鍵字和保留字命名。
2.6 建議使用駝峰命名法。
類名的首字母大寫;變數名、方法名首字母小寫;包名全部小寫;特殊含義的縮略詞全部大寫;常量名全部大寫;多個單詞可以使用下劃線分割。做到見名知意,不要使用拼音字母縮寫、拼音全拼、英文拼音混合的命名格式,不知道如何翻譯請查字典或線上翻譯單詞。變數名長一點無所謂,命名合理、規範,見名知意就可以。
3、變數的使用
實例變數的使用,需要使用new關鍵字創建對象,再通過對象引用。靜態變數可以直接使用。在使用變數前,請先初始化賦值,不能聲明不賦值直接使用。
package javalearningday02; /** * 變數的使用 * @author 小川94 * @date 2018年1月21日 */ public class UseVariable { // 成員變數,也可以稱為全局變數,可在本類或者其他類中使用 private int age = 18; // 聲明一個靜態常量,成員變數的一種,也是一個類變數 private static final String GENDER = "BOY"; // 常量,由關鍵字final定義 private final String NAME = "小川94"; public static void main(String[] args) { // 在main方法中定義的局部變數 int anotherAge = 20; // 變數的定義 int a; // 單個變數定義 int b = 2; // 單個變數定義並初始化 int c,d; // 單次定義多個變數 int _num = 1; // 可以是下劃線開頭,但是不建議 int num_ = 2; // 可以下劃線結尾 int $num; // 也可以美元符號開頭 int num2; // 可以是數字結尾 //int +num; // 錯誤寫法,不能用運算符開頭 //int .num; // 錯誤寫法,不能用.號開頭 //int 2num; // 錯誤寫法,不能以數字開頭 //int *num; // 錯誤寫法,不能以*開頭,其他特殊符號也是不可以的 int 變數 = 2; // 可以使用中文,但是建議不要使用 // 不能使用關鍵字命名 //int class; // 不能使用關鍵字 //int goto; // Java保留關鍵字(保留關鍵字是指那些現有Java版本還未使用的關鍵字,但還是關鍵字) //int const; // Java保留關鍵字 // 不能使用保留字命名 /* int true; int false; int null;*/ } public static String askName(String name){ // 局部變數只能在該變數定義並且初始化的操作域中使用,跨域使用會報錯 // 錯誤寫法 anotherAge cannot be resolved to a variable //System.out.println(anotherAge); // 不能對非靜態變數進行靜態引用 // 錯誤寫法 cannot make a static reference to the non-static field age // System.out.println(age); // 對於全局變數的引用,如果是非靜態的,需要利用對象引用 UseVariable useVariable = new UseVariable(); System.out.println(useVariable.age); // 類變數(靜態成員變數)可以直接使用 System.out.println("小川94的性別是"+GENDER); return "Hello "+name; } }
二、運算符
知道了數據類型,知道如何聲明一個變數並初始化,下麵就開始做數據運算操作。
1、賦值運算符。
=(賦值),要和數學中的等號區分。
2、算術運算符。
+(加法)、-(減法)、*(乘法)、/(除法)、%(取餘)。這五種是開發中比較常用的。
關於除法:
(1)如果被除數是0,運行則會報算術異常,在做除法時需要判斷被除數是否為0。
(2)如果是兩個整數做除法,可能會丟失計算精度,選擇合適的數據類型尤為重要。
關於取餘:
(1)負數對整數的餘數是負數和0。
(2)正數的餘數是有周期性變化的。
(3)餘數是有範圍的數,可以控制數據範圍。
3、數值類型之間的轉換
數值之間的轉換可以分為自動轉換、強制轉換兩種形式。
3.1 自動轉換
如果兩個數中有一個為double類型,另一個數會被轉為double類型,然後再進行運算。
如果兩個數中有一個為float類型,另一個數會被轉為float類型,然後再進行運算。
如果兩個數中有一個為long類型,另一個數會被轉為long類型,然後再進行運算。
如果沒有上述的三種的類型,兩個數都會被轉為int進行運算。
小範圍的數據類型可以自動轉換到大範圍數據類型,大範圍的數可以涵蓋小範圍的數,小範圍內的數可以映射到大範圍內的數。
3.2 強制類型轉換
從大範圍的數向小範圍的數轉換,稱之為強制轉換,用法是在目標數據前使用括弧,將想要轉換的類型輸入括弧即可。
關於強制轉換,有幾點需要註意:
(1)範圍內的數,轉換是沒有損失的。
(2)double轉換為float,會出現精度損失。
(3)浮點數轉換為整數,只會保留原數的整數位,不會保留小數位,也不會進行四捨五入操作。
(4)範圍外的數,會有溢出的風險。
4、結合賦值和運算符
有時候為了省事,會把算術運算符和賦值運算符連著一起寫。如:int n += 4; 這一句和int n = n+4;是等價的,其他的算術運算符也是如此,可以單獨寫在賦值符號的前面。
5、自增、自減運算符
自增的語法是 變數++; 自減的語法是 變數--; 作用是將變數的值增加1,註意是變數,不是整體。
先加加(++變數)和後加加(變數++)在運算時有很大的不同。
(1)先加加,這裡為了方便簡寫為++n吧,是先將n的值加1,然後取n的值作為表達式(++n)整體的值。
int b = ++a;
-->第一步 a = a+1;
-->第二步 b = a;
(2)後加加,同樣為了方便簡寫為n++;是先將n的值作為表達式(n++)整體的值,然後將n的值加1。
int b = a++;
-->第一步 b = a;
-->第二步 a = a+1;
/** * 後加加,先將變數值賦給整體表達式,再計算n+1。後減減同理。 */ public static void selfAddAfter() { int n = 5; n = n++; n = n++; n = n++; n = n++; System.out.println("n的值是"+n); // n = 5; } /** * 先加加,先將變數值加1,再將加過1後的值賦給整體表達式。先減減同理 */ public static void selfAddBefore() { int m = 5; int n = ++m; System.out.println("m的值是"+m); // m = 6; System.out.println("n的值是"+n); // n = 6; }
6、關係運算符
關係運算符,也可以稱為比較運算符,包括>(大於)、<(小於)、>=(大於等於)、<=(小於等於)、==(等於)、!=(不等於),比較的結果為true或false。
7、邏輯運算符
邏輯運算符,包含&&(邏輯與運算)、||(邏輯或運算)、!(邏輯非運算)
在進行邏輯運算時,會出現短路運算的情況,即前一個邏輯判斷已經可以為結果定性,後面的邏輯判斷是不會執行的。
/** * 邏輯運算符 */ public static void logicOperation() { // false,並且發生了短路運算,因為3>4為false,可以直接為整個表達式定性,無需再判斷4>5表達式的值 // 與運算中,所有條件都為true時,整體表達式才為true System.out.println(3>4 && 4>5); // 4>5下麵標黃了,提示是Dead code,說明不會運行後半部分的表達式 // true,這裡也發生了短路運算,不會去判斷3>4的值 System.out.println(2>1 || 3>4); // 或運算中,只要有一個為true,整個表達式的值就是true System.out.println(3>4 || 2>1); // true,非運算中,true變false,false變true System.out.println(!(4>5)); }
8、位運算符
與(&)、非(~)、或(|)、異或(^)、<<(帶符號左移)、>>(帶符號右移)、>>>(無符號右移),下麵將詳細介紹這七種運算符。
8.1 與(&)運算
/** * 與(&)運算 * 規則:先將要運算的數轉為二進位,當相同的位上均為1時結果為1,否則結果為0 */ public static void andOperation() { /** * 98的原碼: 00000000 00000000 0000000 01100010 * 18的原碼: 00000000 00000000 0000000 00010010 * 與運算後: 00000000 00000000 0000000 00000010 * 轉換為十進位的數是2 */ int num = 98&18; System.out.println("(98&18)的與(&)運算結果:"+num); // num = 2 }
8.2 非(~)運算
/** * 非(~)運算 * 規則: 正數的非運算是先取反再計算補碼,負數的非運算是先計算補碼再取反 */ public static void nonOperation() { byte num = ~90; /** * 正數非運算:原碼 -->取反(1變0,0變1,非運算)-->反碼(符號位不變,其餘1變0,0變1)--->補碼(反碼的基礎上加1) * 90 * 原碼: 00000000 00000000 00000000 01011010 * 取反: 11111111 11111111 11111111 10100101 * 反碼: 10000000 00000000 00000000 01011010 * 補碼: 10000000 00000000 00000000 01011011 * 轉為十進位數則是-91 */ System.out.println("90的非(~)運算結果:"+num); // num = -91 /** * 10 * 原碼: 00000000 00000000 00000000 00001010 * 取反: 11111111 11111111 11111111 11110101 * 反碼: 10000000 00000000 00000000 00001010 * 補碼: 10000000 00000000 00000000 00001011 * 轉為十進位數是-11 */ System.out.println("10的非(~)運算結果:"+(~10)); // -11 /** * 負數非運算:原碼 --->反碼(符號位不變,其餘1變0,0變1)--->補碼(反碼的基礎上加1)--->取反(1變0,0變1,非運算) * -5 * 原碼: 10000000 00000000 00000000 00000101 * 反碼: 11111111 11111111 11111111 11111010 * 補碼: 11111111 11111111 11111111 11111011 * 取反: 00000000 00000000 00000000 00000100 * 轉為十進位為 4 */ System.out.println("(-5)的非(~)運算結果:"+(~(-5))); // 4 }
8.3 或(|)運算
/** * 或(|)運算 * 規則:當兩邊操作數的位有一邊為1時,結果為1,否則為0。 */ public static void orOperation() { /** * 23的原碼: 00000000 00000000 00000000 00010111 * 75的原碼: 00000000 00000000 00000000 01001011 * 或運算: 00000000 00000000 00000000 01011111 * 轉換為十進位數是95 */ System.out.println("(23|75)的或(|)運算結果"+(23|75)); // 95 }
8.4 異或(^)運算
/** * 異或(^)運算 * 規則:兩邊的對應位不同時,取1,否則取0。如果遇到負數,需要用負數的補碼進行計算 */ public static void differentOr() { /** * 17的原碼: 00000000 00000000 00000000 00010001 * 29的原碼: 00000000 00000000 00000000 00011101 * 異或運算: 00000000 00000000 00000000 00001100 * 轉為十進位數是12 */ System.out.println("(17^29)的異或(^)運算結果:"+(17^29)); //12 /** * -17的原碼: 10000000 00000000 00000000 00010001 * -17的反碼: 11111111 11111111 11111111 11101110 * -17的補碼: 11111111 11111111 11111111 11101111 * 29的補碼: 00000000 00000000 00000000 00011101 * 運算結果: 11111111 11111111 11111111 11110010 * 對結果反碼: 10000000 00000000 00000000 00001101 * 對結果補碼: 10000000 00000000 00000000 00001110 * 結果轉為十進位數是-14 */ System.out.println("(-17^29)的異或(^)運算結果:"+(-17^29)); //-14 }
8.5 帶符號左移(<<)運算
/** * 帶符號左移(<<)運算 * 規則: 符號位不變,左移幾位,則在補碼(正數的補碼、反碼與原碼一樣)的後面補幾個0 * 也可以簡單理解成數學運算,左移幾位,就是原數乘以2的幾次方 */ public static void withSymbolToLeft() { /** * 10的原碼: 00000000 00000000 00000000 00001010 * 左移四位: 00000000 00000000 00000000 10100000 * 轉換為十進位數是160 * 也可以理解成數學運算中的 10*(2*2*2*2) = 10*16 = 160 */ System.out.println("(10<<4)帶符號左移(<<)運算的結果:"+(10<<4)); // 160 /** * -9的原碼: 10000000 00000000 00000000 00001001 * -9的反碼: 11111111 11111111 11111111 11110110 * -9的補碼: 11111111 11111111 11111111 11110111 * 左移4位: 11111111 11111111 11111111 01110000 * 再反碼: 10000000 00000000 00000000 10001111 * 再補碼: 10000000 00000000 00000000 10010000 * 轉為十進位數是-144 * 也可以理解成數學運算中的 (-9)*(2*2*2*2) = (-9)*16 = -144 */ System.out.println("(-9)<<4)帶符號左移(<<)運算的結果:"+((-9)<<4)); // -144 }
8.6 帶符號右移(>>)運算
/** * 帶符號右移(>>)運算 * 規則: 正數右移時,右移幾位,在補碼的左邊加幾個0,右邊的被自動擠掉; * 負數右移時,右移幾位,在補碼的左邊加幾個1,右邊的被自動擠掉 */ public static void withSymbolToRight() { /** * 20的原碼: 00000000 00000000 00000000 00010100 * 右移4位: 00000000 00000000 00000000 00000001 * 轉為十進位數是1 */ System.out.println("(20>>4)帶符號右移(>>)運算結果:"+(20>>4)); /** * -86的原碼: 10000000 00000000 00000000 01010110 * -86的反碼: 11111111 11111111 11111111 10101001 * -86的補碼: 11111111 11111111 11111111 10101010 * 右移四位: 11111111 11111111 11111111 11111010 * 再計算反碼: 10000000 00000000 00000000 00000101 * 再計算補碼: 10000000 00000000 00000000 00000110 * 轉為十進位數是-6 */ System.out.println("(-86)>>4帶符號右移(>>)運算結果:"+((-86)>>4)); // -6 }
8.7 無符號右移(>>>)運算
/** * 無符號右移(>>>)運算 * 規則: 無論正數還是負數,右移幾位,則在其補碼左邊加上幾個0 */ public static void noSymbolToRight() { /** * 50的原碼: 00000000 00000000 00000000 00110010 * 右移4位: 00000000 00000000 00000000 00000011 * 轉為十進位數是3 */ System.out.println("(50>>>4)的無符號右移(>>>)運算結果:"+(50>>>4)); // 3 /** * -28的原碼: 10000000 00000000 00000000 00011100 * -28的反碼: 11111111 11111111 11111111 11100011 * -28的補碼: 11111111 11111111 11111111 11100100 * 右移四位: 00001111 11111111 11111111 11111110 * 再轉為十進位數是 0+0+0+0+134217728+67108864+33554432+16777216 * +8388608+4194304+2097152+1048576+524288+262144+131072+65536 * +32768+16384+8192+4096+2048+1024+512+256 * +128+64+32+16+8+4+2+0 = 268435454 */ System.out.println("(-28)>>>4的無符號右移(>>>)運算結果:"+((-28)>>>4)); // 268435454 }
9 三目運算符
語法為 條件 ? 條件為true執行 : 條件為false執行 。可以單個寫,也可以多層嵌套,但是如果條件比較複雜,建議單獨抽出來處理,便於閱讀和維護。
public static void threeHeadOperation() { int n = 3; int m = 10; int maxNum = n>m ? n : m; //單個寫法 System.out.println(maxNum); // maxNum = 10 // 設定忽略num小於0的情況 int num = 4; String str = num != 0 ? num%2 == 0 ? "是偶數" : "是奇數" : "是0"; System.out.println(str); // 是偶數 // 上面的三目運算符等價於下麵的代碼 if (num != 0) { if (num%2 == 0) { System.out.println("num是偶數"); } else { System.out.println("num是奇數"); } } else { System.out.println("num是0"); } }
10 instanceof
public class JavaOperation { public static void main(String[] args) { instanceOfOperation(); }
/** * instanceof 是用來在運行時指出對象是否是特定類的一個實例 */ public static void instanceOfOperation() { A a = new A(); String str = a instanceof A ? "a是A的實例" : "a不是A的實例"; System.out.println(str); // a是A的實例 String str2 = null instanceof A ? "null是A的實例" : "null不是A的實例"; System.out.println(str2); // null不是A的實例 } } class A{ }
Java入門(三)源碼已經上傳Github,地址:https://github.com/XiaoChuan94/javalearning/tree/master/javalearningday02,可以參考。
文章首發於我的個人公眾號:悅樂書。喜歡分享一路上聽過的歌,看過的電影,讀過的書,敲過的代碼,深夜的沉思。期待你的關註!
公眾號後臺輸入關鍵字“Java學習電子書”,即可獲得12本Java學習相關的電子書資源,如果經濟能力允許,還請支持圖書作者的紙質正版書籍,創作不易。