Java語言基礎組成
- 關鍵字
-
- 定義:被Java語言賦予了特殊含義的單詞
- 特點:關鍵字中所有字母都爲小寫
- 標識符
-
- 由26個英文字母大小寫,數字,下劃線_,美元符號$ 組成。
- 數字不可以開頭。
- 不可以使用關鍵字。
- 嚴格區分大小寫。
- Java中的名稱規範:
- 包名:多單詞組成時所有字母都小寫。
xxxyyyzzz - 類名接口名:多單詞組成時,所有單詞的首字母大寫。
XxxYyyZzz - 變量名和函數名:多單詞組成時,第一個單詞首字母小寫,第二個單詞開始每個單詞首字母大寫。
xxxYyyZzz - 常量名:所有字母都大寫。多單詞時每個單詞用下劃線連接。
XXX_YYY_ZZZ
- 包名:多單詞組成時所有字母都小寫。
- 註釋
-
- 對於文檔註釋,是java特有的註釋,其中註釋內容可以被JDK提供的工具javadoc 所解析,生成一套以網頁文件形式體現的該程序的說明文檔。
- 常量與變量
-
- 常量:
- 常量表示不能改變的數值。
- Java中常量的分類:
- 整數常量。
- 三種表現形式:
- 十進制:0-9 ,滿10進1.
- 八進制:0-7 ,滿8進1. 用0開頭表示。
- 十六進制:0-9,A-F,滿16進1. 用0x開頭表示。
- 三種表現形式:
- 小數常量。
- 布爾型常量。只有兩個數值,true、false。
- 字符常量。將一個數字、字母或者符號用單引號( ' ' )標識。
- 字符串常量。將一個或者多個字符用雙引號標識。
- null常量。只有一個數值就是:null.
- 整數常量。
- 進制的基本轉換
- 十進制與二進制互轉
- 十進制轉成二進制:除以2取餘數,逆序排列。
- 二進制轉成十進制:乘以2的冪數
- 十進制與八進制互轉:先將十進制與二進制互轉,再將二進制與八進制互轉
- 十進制與十六進制互轉:先將十進制與二進制互轉,再將二進制與十六進制互轉
- 負數的二進制表現形式:
- 對應的正數二進制取反加1。
- 一個整數佔四個字節,負數的最高位都是1。
- 十進制與二進制互轉
- 變量:
- 概念:在內存中開闢一個空間,該空間有自己的名稱(變量名)和類型(數據類型),在該空間內存儲不確定的數據。
- 變量的作用範圍:一對{}之間有效,但不能違背先定義後使用的原則。
- 局部變量在進行取值操作前,必須被初始化或進行賦值操作,否則會出現編譯錯誤。
- 定義變量的格式:數據類型 變量名 = 初始化值;
- Java語言是強類型語言,對於每一種數據都定義了明確的具體數據類型,在內存總分配了不同大小的內存空間:
數據類型 取值範圍 byte 1個字節 short 2個字節 int 4個字節 long 8個字節 float 4個字節 double 8個字節 char 2個字節 public class Calcsizof { /** * @param args */ private static void calSize() { System.out.println("Integer: " + Integer.SIZE/8); // 4 System.out.println("Short: " + Short.SIZE/8); // 2 System.out.println("Long: " + Long.SIZE/8); // 8 System.out.println("Byte: " + Byte.SIZE/8); // 1 System.out.println("Character: " + Character.SIZE/8); // 2 System.out.println("Float: " + Float.SIZE/8); // 4 System.out.println("Double: " + Double.SIZE/8); // 8 System.out.println("Boolean: " + Boolean.toString(false)); } public static void main(String[] args) { // TODO Auto-generated method stub Calcsizof calcsizof= new Calcsizof(); Calcsizof.calSize(); } }
運行結果:console 輸出
Integer: 4
Short: 2
Long: 8
Byte: 1
Character: 2
Float: 4
Double: 8
Boolean: false - 整數的默認類型爲int,小數的默認類型爲double。
- 表達式的數據類型自動提升:
- 所有的byte型、short型和char的值將被提升到int型。
- 如果一個操作數是long型,計算結果就是long型;
- 如果一個操作數是float型,計算結果就是float型;
- 如果一個操作數是double型,計算結果就是double型。
- 常量:
- 運算符
-
- 算術運算符
- 算數運算符如下圖:
- 如果對負數取模,可以把模數負號忽略不記,但被模數如果是負數,負號不能忽略。如:5%-2=1、-5%2=-1。
- 使用“+”連接字符串與非字符串,非字符串會先被轉換成字符串,再與其他字符串連接。
- 算數運算符如下圖:
- 轉義字符:
- 通過“\”來轉變後面字母或者符號的含義
\n 換行 \b 退格 \r 回車 \t 製表符 \" 打印雙引號 \\ 打印\ - windows中回車由兩個字符來表示\r\n
- 通過“\”來轉變後面字母或者符號的含義
- 賦值運算符
- 賦值運算符如下圖:
- 面試問題:
- short s = 3;
s=s+2;
s+=2;
上面兩句有什麼區別? - s=s+2;//編譯失敗,因爲s會被提升爲int類型,運算後的結果還是int類型,無法賦值給short類型。
s+=2;//編譯通過,因爲+=運算符在給s賦值時,自動完成強制類型轉換。
- short s = 3;
- 賦值運算符如下圖:
- 比較運算符:
- 比較運算符如下圖:
- 比較運算符的結果都是boolean型,要麼是true,要麼是false。
- 比較運算符如下圖:
- 邏輯運算符
- 邏輯運算符如下圖:
- 邏輯運算符用於連接布爾型表達式,在Java中不可以寫成3<x<6,應該寫成x>3 & x<6 。
- “&”和“&&”的區別:
- 單&時,左邊無論真假,右邊都進行運算;
- 雙&時,如果左邊爲真,右邊參與運算,如果左邊爲假,那麼右邊不參與運算。
- “|”和“||”的區別同理,雙或時,左邊爲真,右邊不參與運算。
- 異或( ^ )與或( | )的不同之處是:當左右都爲true時, 結果爲false。
- 邏輯運算符如下圖:
- 位運算符
- 位運算符如下圖:
- 位運算是直接對二進制進行運算。
- 位運算符的細節如下圖:
- 一個數異或同一個數兩次,結果還是這個數。如:7 ^ 4 ^ 4 = 7,這個規律可以作爲加密的一個應用,4相當於一個祕鑰。
- 移位運算符適用的數據類型:byte,short,int,long,char。
- 對低於int類型的操作數將先自動轉換爲int類型再移位。
- 對於int型整數移位a>>b,系統先將b對32取模,得到的結果纔是真正移位的位數。
例如:a >> 33和a >> 1的結果是一樣的。
a >> 32的結果還是a。 - 對於long型整數移位a>>b,系統先將b對64取模,得到的結果纔是真正移位的位數。
- 注意,移位操作不會改變變量本身的值。
如a >> 1;在一行語句中單獨存在毫無意義,因爲它沒有改變a的值,也沒有把它賦給別的變量。 - <<:相當於乘以2的移動的位數次冪。
- >>:相當於除以2的移動的位數次冪(該規律只對正數有效)。
- 利用位運算進行乘除運算的效率是最高的。
- 位運算的應用:
- 十進制轉十六進制:利用&15,>>>4,依次獲得從最低位開始的每四位二進制數對應的十六進制數。
- 十進制轉八進制:利用&7,>>>3,依次獲得從最低位開始的每三位二進制數對應的八進制數。
- 位運算符如下圖:
- 三元運算符
- 格式:
- (條件表達式)?表達式1:表達式2;
- 如果條件爲true,運算後的結果是表達式1;
- 如果條件爲false,運算後的結果是表達式2;
- 格式:
- 算術運算符
- 程序流程控制
-
- 判斷結構:if語句
- if語句的三種格式:
- if語句第二種格式與三元運算符的區別:
- 三元運算符可以簡化if-else代碼
- 三元運算符要求表達式1和表達式2必須爲一個可以返回的結果。而if-else語句不要求必須返回結果。
- if語句的三種格式:
- 選擇結構:switch語句
- switch語句的格式:
- switch語句特點:
- switch語句選擇的類型只有四種:byte,short,int ,char。
- case之間與default沒有順序。先執行第一個case,沒有匹配的case才執行default。
- 結束switch語句的兩種情況:遇到break,執行到switch語句結束。
- 如果匹配的case或者default沒有對應的break,那麼程序會繼續向下執行,運行可以執行的語句,直到遇到break或者switch結尾結束。
- switch語句的格式:
- 循環結構:while , do-while , for語句
- while語句格式:
- do-while語句格式:
- for語句格式:
- do-while語句的特點是條件無論是否滿足,循環體至少被執行一次。
- for語句裏面的表達式運行的順序是,初始化表達式只讀一次,判斷循環條件,爲真就執行循環體,然後再執行循環後的操作表達式,接着繼續判斷循環條件, 重複這個過程,直到條件不滿足爲止。
- while與for語句可以互換,區別在於for語句的計數器爲局部變量,while語句的計數器爲成員變量。
- 最簡單無限循環格式:
while(true){}
for(;;){}//for的條件表達式默認爲true
- while語句格式:
- 其他流程控制語句:break(跳出),continue(繼續)
- break語句用於選擇結構和循環結構。
- continue語句用於循環結構。
- 這個兩個語句單獨存在下面都不可以有語句,因爲執行不到。
- continue語句是結束本次循環繼續下次循環。
- break和continue都可以使用循環標記,用於跳出循環。
- 判斷結構:if語句
- 函數
-
- 函數的定義
- 函數就是定義在類中的具有特定功能的一段獨立小程序。
- 函數的格式:
返回值類型:函數運行後的結果的數據類型。
參數類型:是形式參數的數據類型。
形式參數:是一個變量,用於存儲調用函數時傳遞給函數的實際參數。
實際參數:傳遞給形式參數的具體數值。
return:用於結束函數。
返回值:該值會返回給調用者。
- 函數的特點
- 定義函數可以將功能代碼進行封裝
- 函數的出現提高了代碼的複用性
- 對於函數沒有具體返回值的情況,返回值類型用關鍵 字void表示,那麼該函數中的return語句如果在最後一行可以省略不寫。
- 函數中只能調用函數,不可以在函數內部定義函數。
- 函數的應用
- 明確要定義的功能最後的結果是什麼,即明確函數的返回值類型。
- 明確在定義該功能的過程中,是否需要未知內容參與運算,即明確函數的參數列表。
- 函數的重載(overload)
- 概念:在同一個類中,允許存在一個以上的同名函數,只要它們的參數個數或者參數類型不同即可。
- 特點:重載只看參數列表。重載的函數返回值類型可以相同也可以不同。
- 好處:方便於閱讀,優化了程序設計。
- 函數的定義
- 數組
-
- 數組的定義
- 概念:同一種類型數據的集合。數組就是一個容器。
- 好處:可以自動給數組中的元素從0開始編號,方便操作這些元素。
- 格式:
- 元素類型[] 數組名= new 元素類型[元素個數或數組長度];
示例:int[] arr = new int[5];//arr是數組類型(引用數據類型) - 元素類型[] 數組名= new 元素類型[]{元素,元素,……};//靜態初始化
示例:int[] arr = new int[]{3,5,1,7};
int[] arr = {3,5,1,7};
- 元素類型[] 數組名= new 元素類型[元素個數或數組長度];
- 數組的內存分配
- Java將內存分爲五個區域:棧內存,堆內存,方法區,本地方法區,寄存器。
- 棧內存:用於存儲局部變量,包括函數中定義的一些基本類型的變量和對象的引用變量。當數據使用完,所佔空間會自動釋放。
- 堆內存:用於存儲有new創建的對象和數組,包括對象的成員變量。當數據使用完,會在不確定的時間內被垃圾回收器回收。
- 方法區:用於存儲被加載的類信息、靜態變量和常量。
- 堆內存中的元素都有默認初始化值:
元素類型 默認初始化值 int 0 double 0.0 float 0.0f boolean false 引用類型 null - 詳細見:JVM的內存區域劃分(轉)
- 垃圾回收機制:
- 棧內存中的垃圾會自動釋放。局部變量在程序運行到其作用域之外後被釋放。
- 堆內存中的垃圾會由虛擬機不定時進行垃圾回收。數組和對象在沒有引用變量指向它時,會變爲垃圾,並在隨後一個不確定的時間被回收。因此,java程序比較佔內存。
- 對象被當成垃圾從內存中釋放前(不是對象變成垃圾前),會調用Object類的finallize()方法啓用垃圾回收器。垃圾回收器的啓用不由程序員控制,也無規律可循,甚至有可能到程序終止都沒有啓動的機會,因此它不是一個可靠的機制,我們無法保證每個對象的finallize()方法最終都會被調用。
- System.gc()方法可以強制啓動垃圾回收器來回收垃圾。程序在調用該方法時,JVM會根據需要在單獨的線程中自動執行回收過程。
- 數組內存結構如下圖:
- Java將內存分爲五個區域:棧內存,堆內存,方法區,本地方法區,寄存器。
- 數組操作常見問題:
- ArrayIndexOutOfBoundsException:數組越界異常。訪問到了數組中的不存在的角標時發生。
- NullPointerException:空指針異常。當引用沒有任何指向,且被用於操作實體時發生。
- 注意:以上兩個異常,編譯時不會報錯,運行時纔會報錯,都屬於RuntimeException
- 數組常見操作
- 遍歷:
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,5,8,45,56,79,35}; printArray(arr); } //定義功能,用於打印數組中的元素,元素間用逗號隔開 public static void printArray(int[] arr){ //遍歷數組 for (int i = 0; i < arr.length; i++) { //如果不是最後一個元素,在元素後面打印一個逗號 //否則在元素後面打印回車換行 if (i != arr.length - 1) { System.out.print(arr[i] + ","); } else { System.out.println(arr[i]); } } } }
- 獲取最值(最大值,最小值):
- 方法一:定義臨時變量存儲最大值和最小值
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,5,8,45,56,79,35}; int max = getMax(arr); int min = getMin(arr); System.out.println("max = " + max); System.out.println("min = " + min); } //獲取數組中的最大值 public static int getMax(int[] arr){ int max = arr[0];//數組中的最大值 for (int i = 1; i < arr.length; i++) { if (max < arr[i]) { max = arr[i]; } } return max; } //獲取數組中的最小值 public static int getMin(int[] arr){ int min = arr[0];//數組中的最小值 for (int i = 1; i < arr.length; i++) { if (min > arr[i]) { min = arr[i]; } } return min; } }
- 方法二:定義臨時變量存儲最大值和最小值的下標
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,5,8,45,56,79,35}; int max = getMax(arr); int min = getMin(arr); System.out.println("max = " + max); System.out.println("min = " + min); } //獲取數組中的最大值 public static int getMax(int[] arr){ int max = 0;//數組中的最大值的下標 for (int i = 1; i < arr.length; i++) { if (arr[max] < arr[i]) { max = i; } } return arr[max]; } //獲取數組中的最小值 public static int getMin(int[] arr){ int min = 0;//數組中的最小值的下標 for (int i = 1; i < arr.length; i++) { if (arr[min] > arr[i]) { min = i; } } return arr[min]; } }
- 方法一:定義臨時變量存儲最大值和最小值
- 排序:
- 選擇排序
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,8,5,45,56,79,35}; printArray(arr);//打印排序前的數組 selectSort(arr); printArray(arr);//打印排序後的數組 } //選擇排序方法 //定義嵌套循環,內循環結束一次,i所在下標位上的最值出現一次 public static void selectSort(int[] arr){ //確定arr[i]元素排序後對應的值 for (int i = 0; i < arr.length - 1; i++) { //arr[i]依次和後面的arr[j]進行比較 //如果arr[i] > arr[j],則交換兩個元素的位置 //內循環結束後,arr[i]的值小於所有後面元素的值 for (int j = i + 1; j < arr.length; j++) { if (arr[i] > arr[j]) { swap(arr, i, j); } } } } //交換數組中指定元素的位置 public static void swap(int[] arr, int a,int b){ int temp; temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } //打印數組中的元素 public static void printArray(int[] arr){ System.out.print("["); for (int i = 0; i < arr.length; i++) { if (i != arr.length - 1) { System.out.print(arr[i] + ","); } else { System.out.println(arr[i] + "]"); } } } }
- 冒泡排序
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,8,5,45,56,79,35}; printArray(arr);//打印排序前的數組 bubbleSort(arr); printArray(arr);//打印排序後的數組 } //冒泡排序方法 //定義嵌套循環,內循環結束一次,(arr.length - i - 1)所在下標位上的最值出現一次 public static void bubbleSort(int[] arr){ //控制循環次數,每循環一次,(arr.length - i - 1)所在下標位上出現最大值 for (int i = 0; i < arr.length - 1; i++) { //從0下標位開始依次比較相鄰的兩個元素 //如果arr[j] > arr[j + 1],交換兩個元素的位置 //內循環結束後,arr[j + 1]的值大於所有前面元素的值 for (int j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { swap(arr, j, j + 1); } } } } //交換數組中指定元素的位置 public static void swap(int[] arr, int a,int b){ int temp; temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } //打印數組中的元素 public static void printArray(int[] arr){ System.out.print("["); for (int i = 0; i < arr.length; i++) { if (i != arr.length - 1) { System.out.print(arr[i] + ","); } else { System.out.println(arr[i] + "]"); } } } }
- 以上兩種的運行效率不是很高,實際開發中可以選擇Arrays.sort方法進行排序。
- 選擇排序
- 折半查找(二分查找):前提條件是數組爲有序數組。
- 方法一:
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,5,8,35,45,56,79}; System.out.println("index = " + halfSearch(arr, 8)); System.out.println("index = " + halfSearch(arr, 60)); } //折半查找,返回對應的數組下標,如果沒有匹配的元素,則返回-1 public static int halfSearch(int[] arr, int key){ int min = 0;//下標範圍最小值 int max = arr.length - 1;//下標範圍最大值 int mid = (min + max)/2;//用於折半的下標中間值 //如果key與當前arr[mid]對應元素不相等,循環折半查找 while (key != arr[mid]) { //如果key比中間值小,下標範圍最大值應移至中間下標左側 if (key < arr[mid]) { max = mid - 1; } //如果key比中間值大,下標範圍最小值應移至中間下標右側 else { min = mid + 1; } //如果下標範圍最大值小於下標範圍最小值 //說明數組中沒有與key匹配的元素,返回-1 if (max < min) { return -1; } //重新計算用於折半的下標中間值 mid = (min + max)/2; } return mid; } }
- 方法二:
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,5,8,35,45,56,79}; System.out.println("index = " + halfSearch(arr, 8)); System.out.println("index = " + halfSearch(arr, 60)); } public static int halfSearch(int[] arr, int key){ int min = 0;//下標範圍最小值 int max = arr.length - 1;//下標範圍最大值 int mid;//用於折半的下標中間值 //如果下標範圍最小值不大於下標範圍最大值,循環折半查找 while (min <= max) { mid = (min + max)/2;//計算當前的下標中間值 //如果key比中間值小,下標範圍最大值應移至中間下標左側 if (key < arr[mid]) { max = mid - 1; } //如果key比中間值大,下標範圍最小值應移至中間下標右側 else if(key > arr[mid]){ min = mid + 1; } //如果key等於中間值,則返回中間值的下標 else{ return mid; } } return -1;//沒有匹配的元素 } }
- 練習:有一個有序的數組,想要將一個元素插入到該數組中,且保證該數組還是有序的。
package cn.itcast.heima; public class Test { public static void main(String[] args) { int[] arr = {3,5,8,35,45,56,79}; System.out.println("index = " + getIndex(arr, 8)); System.out.println("index = " + getIndex(arr, 80)); } public static int getIndex(int[] arr, int key){ int min = 0; int max = arr.length - 1; int mid; while (min <= max) { mid = (min + max)/2; if (key < arr[mid]) { max = mid - 1; }else if(key > arr[mid]){ min = mid + 1; }else{ return mid; } } return min;//數組中沒有與key匹配的元素,將key插入min下標的位置 } }
- 方法一:
- 遍歷:
- 二維數組:
- 格式1:int[][] arr = new int[3][2];
- 格式2:int[][] arr = new int[3][];//每個一維數組都是默認初始化值null
- 格式3:int[][] arr = {{3,8,2},{2,7},{9,0,1,6}};
- 注意特殊寫法情況:int[] x,y[]; x是一維數組,y是二維數組。
- 數組的定義