Java基礎(變數、資料型別、運算子、分支結構、迴圈結構、陣列、方法)
1Java基礎
1.1變數
1.1.1簡介
變數是一個代詞,指代在計算機的記憶體中的一塊空間,用來儲存程式在執行中所需要的資料。
1.1.2命名規則
- 只能包含字母、數字、_和$,並且不能以數字開頭;
- 不能使用關鍵字/保留字(是關鍵字的一種,但是佔著不用);51+2
- 嚴格區分大小寫(對大小寫敏感);
- 可以是中文、日文、韓文等命名,但不建議,有可能亂碼;
- 建議:英文的見名知意、駝峰命名法,不要使用拼音。
1.1.3宣告
變數的宣告指的是在記憶體中開闢一塊指定大小的記憶體空間,預設還沒有存資料。
語法結構:資料型別 變數名;
// 聲明瞭一個int型別變數num int num; // 聲明瞭三個int型別變數a、b、cint a, b, c;
1.1.4初始化
變數的初始化指的是對變數的第一次賦值。
語法結構:資料型別 變數名 = 值;
1.宣告同時初始化 // 宣告變數num,同時賦值為250 int num = 250; 2.先宣告再初始化 // 宣告變數num int num; // 給num賦值為250 num = 250; 3.同時宣告多個變數(用得較少) // 同時宣告變數a、b、c int a, b, c; // 同時宣告變數a、b、c,並分別賦值為100、200、300 int a=100, b=200, c=300;
1.1.5訪問(操作)
- 變數在使用之前必須要宣告並初始化;
- 變數的操作必須與型別匹配。
1.2資料型別
1.2.1簡介
基本資料型別也叫原生資料型別,Java保留了C語言中的8個基本資料型別,為了計算方便,速度快,但是不能參與面向物件開發。
包裝類S
1.2.2整數相關
- byte : 位元組型,1個位元組(8位),-128 ~ 127,用得一般
- short : 短整型,2個位元組(16位),-32768 ~ 32767,少到幾乎不用
- int : 整型,4個位元組(32位),-2^31 ~ 2^31-1,最常用
- Java中整數直接量預設為int型別,如: 123、250、10000
- 兩個int型別的變數操作,結果還是int型別,小數位無條件捨棄
- long : 長整型,8個位元組(64位),
- long型別的直接量,要在整數後面加l或L,如: 123L、250L
- 如果要計算超出了long範圍的時候,可以使用BigInteger類
1.2.3小數相關
- float : 浮點型,4個位元組(32位),-2^31 ~ 2^31-1,少到幾乎不用
- float型別的直接量,要在小數後面加f或F,如: 3.14F
- double : 雙精度浮點型,8個位元組(64位),-2^63 ~ 2^63-1,最常用
- Java中小數直接量預設為double型別,如: 3.14、6.18
- 有可能會出現舍入誤差,精確運算時要慎用,(因為10進位制與2進位制之間轉換時有可能會損失精度)
- 要做小數的精確計算時,可以使用BigDecimal類
1.2.4其他型別
- char : 字元型,2個位元組(無符號16位),0 ~ 65535
- char型別的直接量,需要放在’’單引號中,單引號中有且僅有1個字元
- 使用Unicode編碼格式,實質上是整數,即char對應的碼,如: A->65,a->97
- ”Java程式設計師”在記憶體中佔多少個位元組?14
- boolean : 布林型,1個位元組(8位),false/true
1.2.5附:面試題
- Java中的原生資料型別有哪些?各自的範圍是多少?
1.3基本資料型別的轉換
1.3.1自動型別轉換,從小型別到大型別
byte --> short --> int --> long --> float --> double --> char
1.3.2強制型別轉換,從大型別到小型別強轉,有可能發生精度丟失、溢位。向下造型
double d = 3.14; //float f = d; //編譯錯誤,大型別不能直接賦值給小型別 float f = (float) d; //將d中的資料強轉成float型別 int i = (int) d; //強制轉換,i=3,精度丟失 long l = 200; byte b = (byte) l; //強制轉換,溢位了
1.3.3附:面試題
- 下面的程式碼編譯是否正確?
short s1 = 10; short s2 = 20; s1 = s1 + s2; //編譯錯誤,因為short型別的運算結果自動變成int型別
1.4運算子
1.4.1算術運算子 + - * / % ++ --
% : 取餘/取模,兩個數相除取餘數,如: 4/3=商1餘1+ 5/3求模
++ : 自增,變數自身加1
++a 先運算後賦值、 a++先賦值後運算
int a = 11; // 先賦值後加1:先把a變數的值10賦給a++表示式(a++=10),然後a變數自身再加1(a=11) int b = a++; Int b=++a; System.out.println(a); //11 System.out.println(b); //10 int x = 10; // 先加1後賦值:x變數先自身加1(x=11),然後再將x變數的值11賦給++x表示式(++x=11) int y = ++x; System.out.println(x); //11 System.out.println(y); //11 int c=5; int f=2;//3 int d=f++; System.out.println(f);//3
-- : 自減,變數自身減1
int a = 10; // 先賦值後減1:先把a變數的值賦給a--表示式(a--=10),然後a變數自身再減1(a=9) int b = a--;//先賦值再減減 System.out.println(a); //9 System.out.println(b); //10 int x = 10; // 先減1後賦值:x變數先自身減1(x=9),然後再將x變數的值9賦給--x表示式(--x=9) int y = --x;//先運算後賦值 System.out.println(x); //9 System.out.println(y); //9
1.4.2關係運算符 > < >= <= == !=
System.out.println( 10 > 5 ); //true
System.out.println( 10 < 5 ); //false
System.out.println( 10 >= 10 ); //true
System.out.println( 10 <= 10 ); //true
System.out.println( 10 == 10 ); //true
System.out.println( 10 != 10 ); //false
- 關係運算符的結果為boolean型別
1.4.3邏輯運算子 && || !
&&: 邏輯與/短路與,兩邊表示式都為true,結果才為true,若左邊的表示式為false時會發生短路(右邊的表示式不再執行了)。
||: 邏輯或/短路或,只要一邊表示式為true,結果就為true,若左邊的表示式為true時會發生短路(右邊的表示式不再執行了)。
! : 非/取反,非真true則假false,非假false則真true
// 判斷是否為閏年:1.年份能被4整除並且不能被100整除,2.年份能直接被400整除 int year = 2020; 3200 boolean b = (year%4==0 && year%100!=0) || year%400==0; System.out.println(“是否為閏年?” + b);
- 邏輯運算子一般配合關係運算符來使用
- 邏輯運算子的結果為boolean型別
1.4.4賦值運算子 = += -= *= /= %=
= : 普通賦值運算子
+= -= *= /= %= : 擴充套件賦值運算子
int a = 10;
a += 20; //相當於: a = a + 20;
- 擴充套件賦值運算子預設有型別轉換的特點
short s1 = 10;
short s2 = 20;
s1 = s1 + s2; //編譯錯誤,short型別運算後的結果是int型別,int不能直接賦給short
s1 +=s2; //編譯通過,相當於: s1 = (short)(s1 + s2);
1.4.5三目運算子
三目運算子也叫三元運算子,因為它是由3個表示式組成的。
語法結構:boolean表示式1? 表示式2: 表示式3;
- 三目運算子的執行過程:
- 先判斷boolean表示式1
- 若boolean表示式1為true,執行:冒號左邊的表示式2,否則執行:冒號右邊的表示式3。 //不建議使用,使用if
// 求兩個數中的最大值
int a = ?;
int b = ?;
int max = a > b? a: b;
System.out.println(max);
- 三目運算子可以巢狀,巢狀之後使程式碼結構不清晰,但是一般不用。
1.4.6字串連線符
+ 即可以用來做算數加法運算,也可以用來做字串的拼接運算。
- 若 + 左右兩邊都是數字型別時,預設做加法運算;
- 若 + 左右兩邊只要有字串型別時,預設做字串拼接執行;
- 字串拼接後,結果還是字串;
int a = 250;
String s1 = “hello”;
String s2 = s1 + a; // “hello”+250 => “hello250”
String str = 5 + 7 + “abc”+ 7 + 5;
System.out.println(str); //”12abc75”
1.4.7位運算子(擴充套件)
位運算子是針對二進位制運算的,常見的位運算子有以下這些:
- &: 位與,兩邊都是1,結果才是1
- |: 位或,兩邊都是0,結果才是0
- ~: 位反,~0=1,~1=0
- ^: 位異或,一邊為1一邊為0時,結果才是1
- >>: 位有符號右移,將二進位制整體向右邊移動,前面補0,保留符號位(正/負)
- <<: 位有符號左移,將二進位制整體向左邊移動,後面補0,保留符號位(正/負)
- >>>: 位無符號右移,將二進位制整體向右邊移動,前面補0,不保留符號位,移完後都是正數
1.4.8附:面試題
- &和&&的區別?
& 和 && 都可以用來做邏輯運算
a)&是位與運算子,&&是邏輯與運算子
b)&不會發生短路,&&是會發生短路的
2. 使用最有效的方式計算 8/4 的結果?
8 >> 2
00001000 >> 2 = 00000010
1.5分支結構
Java程式語言中有三種語法結構,分別是:順序結構、分支結構、迴圈結構。
分支結構指的是根據條件的判斷去決定是否執行某段程式碼,簡單的說就是可以選擇性的去執行某些程式碼。
1.5.1單路分支
單路分支是指如果條件成立了就去執行指定的程式碼,否則就不執行。
語法結構:if(條件) { 條件成立時執行的程式碼... }
int price = ?; if (price >= 500) { System.out.println(“打8折!”); } //超市、 特殊寫法: if(price >=500) System.out.println(“打8折!”); //不常用
1.5.2雙路分支
雙路分支是指如果條件成立了就去執行指定的第一段程式碼,否則就去執行指定的第二段程式碼。場景:一個條件做兩件事情
語法結構:
if(條件) { //true/false
第一段程式碼... true
}else{
第二段程式碼... flase
}
// 判斷年份是否為閏年
int year = 2020;
if (year%4==0 && year%100!=0 || year%400==0) {
System.out.println(year + “是閏年!”);
} else {
System.out.println(year + “不是閏年!”);
}
1.5.3多路分支(巢狀分支)
多路分支是指在多個條件的判斷下,去執行其中條件成立指定的程式碼。場景:多個條件做多件事情,確定一個範圍
語法結構:
if (條件1) {
程式碼塊1
} else if(條件2) {
程式碼塊2
} else if(條件n) {
程式碼塊n
} else {
程式碼塊else
}
// 其實,上面的程式碼是下面巢狀程式碼的簡寫!
if (條件1) {
程式碼塊1
} else {
if(條件2) {
程式碼塊2
} else {
if(條件n) {
程式碼塊n
} else {
程式碼塊else
}
}
}
// 成績等級判斷
int score = ?;
if (score >= 90) {
System.out.println(“A-優秀”);
} else if (score >= 80) {
System.out.println(“B-良好”);
} else if (score >= 70) {
System.out.println(“C-中等”);
} else if (score >= 60) {
System.out.println(“D-及格”);
} else {
System.out.println(“E-不及格”);
}
1.5.4switch case
switch case 也是用來作為多路分支,優點是速度快,缺點是不夠靈活。場景:確定值的時候(不是一個範圍)
語法結構:
switch(表示式) {
case 值1:
程式碼塊1;
break;
case 值2:
程式碼塊2;
break;
case 值n:
程式碼塊n;
break;
default:
程式碼塊default;
}
- switch括號中的表示式結果只能是int和String型別。
- case 後面的值一定要是直接量或常量,不能是變數。
- break 用來中斷switch語句,也就是不要再執行break後面的程式碼;注意:如果沒有break的話,case將會出現穿透的效果(會一路執行到switch內部程式碼的最後,或是一路執行到後面遇到的break為止)。
// 模擬取款機程式
int cmd = ?;
switch (cmd) {
case 1:
System.out.println(“查詢餘額”);
break;
case 2:
System.out.println(“轉賬”);
break;
case 3:
System.out.println(“取款”);
break;
default:
System.out.println(“輸入有誤”);
}
1.6迴圈結構
迴圈指的是反覆/重複去執行一段相同或相似的程式碼。
1.6.1while
語法結構:
while(條件) {
迴圈體程式碼塊
}
執行流程:
當條件成立,就會迴圈執行迴圈體程式碼塊,直到條件不成立為止。
應用場景:
當咱們不知道要迴圈多少次時,也就是說迴圈次數不確定時。
1.6.2do while
語法結構:
do {
迴圈體程式碼塊
} while(條件);
執行流程:
1、先執行一次迴圈體程式碼塊
2、當條件成立,則繼續迴圈執行迴圈體程式碼塊,直到條件不成立為止。
應用場景:
當咱們要先執行一次迴圈體程式碼塊,再進行迴圈條件的判斷時。
在實際的開發中,do while迴圈用的較少。
1.6.3for
語法結構:
for (表示式1;表示式2;表示式3) {
迴圈體程式碼塊
}
說明:
- 表示式1- 迴圈變數的初始化
- 表示式2- 迴圈的條件
- 表示式3- 迴圈變數的改變(注:應該要向著迴圈結束去改變)
執行流程:
- 先執行表示式1,進行迴圈變數的初始化操作,注:只執行一次
- 再執行表示式2,進行迴圈條件的判斷
1)若條件成立,則執行迴圈體程式碼塊
2)若條件不成立,則結束迴圈
- 再執行表示式3,進行迴圈變數的改變
- 依次第2.和第3.步迴圈執行
應用場景:
當迴圈次數固定時,建議使用for迴圈。
1.6.4迴圈的關鍵字
break 是中斷的意思,在迴圈中使用時,可以使當前迴圈結束。注:break只能結束一層迴圈。
continue 是繼續的意思,用在迴圈中,跳過本次迴圈continue後面的程式碼,從而進入下一次迴圈。
int sum = 0;
for(int i = 0; i < 10; i++) {
if(i % 2 == 0){
continue;
}
sum += i;
}
int sum = 0;
for(int i = 0; i < 10; i++) {
if(i == 5){
break;
}
sum += i;
}
System.out.println(sum);
1.6.5迴圈的巢狀
迴圈的巢狀指的是在迴圈中可以巢狀另一個迴圈,可以多層巢狀,但是開發中迴圈的巢狀最好不要超過3層。
// 九九乘法表
for(int i = 1; i <= 9; i++) { //迴圈9次,控制行數
for(int j = 1; j <= i; j++) { //控制列數,列數跟隨行數底層而增加的
System.out.print( i + “*”+ j + “=”+ (i * j) );
}
System.out.println();
}
說明:
外層迴圈執行一次,它的內層迴圈要執行完一輪。
1.7陣列
1.7.1陣列的簡介
- 陣列是指一組資料的集合,陣列中的每個資料稱作為元素。
- 陣列是一種線性表資料結構,它用一組連續的記憶體空間,來儲存一組具有相同型別的資料。
- 同一個陣列中存放的元素的型別必須要一致。
- 在Java中,陣列是一種引用資料型別。
1.7.2陣列的宣告
宣告陣列是指告訴Java陣列的型別是什麼。
// 1.中括號[]寫在型別的後面,Java中推薦這種寫法
int[]arr;
// 2.中括號[]寫在變數名的後面
int arr[];
int[][]arr;
int arr[][];
int[]arr[];
1.7.3陣列的初始化
語法結構:
// 先宣告陣列
int[] arr;
// 對陣列預設初始化
arr = new int[10];
上述程式碼相當於在記憶體中定義了10個int型別的變數,第1個變量表示為arr[0],第2個變量表示為arr[1],以此類推,第10個變量表示為arr[9]。其中的0,1,…,9稱為陣列的下標/索引,下標從0開始,到“陣列的長度-1”結束。
當然,除了上面初始化陣列的方式外,還可以像下面這樣:
// 宣告和初始化寫在一起,陣列中預設每個元素的初始化值為0
int[] arr = new int[10];
// 宣告和初始化一起,但是手動指定初始化的值
int[] arr = {1, 2, 3};
// 宣告和初始化一起,手動指定好初始化的值,注意:[]中括號中不能再指定長度
int[] arr = new int[]{1, 2, 3};
問題:int[] arr = {1,2,3} 與 int[] arr = new int[]{1,2,3} 的區別?
int[] arr = {1,2,3} 只能宣告和初始化寫在一起,不能分開寫,如:
int[] arr;
arr = {1,2,3}; //編譯錯誤的
int[] arr = new int[]{1,2,3} 可以宣告和初始化寫在一起,也可以分開,如:
int[] arr;
arr = new int[]{1,2,3}; //編譯成功
1.7.4陣列的訪問
通過下標/索引來訪問元素,陣列提供了一個length屬性,來獲取陣列的長度(元素的個數)。
int[] arr = {1, 4, 7, 8};
System.out.println(arr.length); //列印陣列的長度:4
arr[0] = 100; //給arr中的第1個數賦值為100,此時:[100, 4, 7, 8]
System.out.println(arr[3]); //輸出arr中的最後一個數:8
System.out.println(arr[arr.length-1]); //靈活的輸出arr中最後一個元素
arr[4] = 88; //錯誤的,下標越界/超範圍,ArrayIndexOutOfBoundsException
1.7.5陣列的遍歷
遍歷是指對陣列中所有元素的訪問,依次對陣列中每個元素訪問一次。
- 順序遍歷
int[] arr = {1, 4, 7};
for(int i=0; i<arr.length; i++){
int a = arr[i]; //arr[0], arr[1], arr[2]
System.out.println(a);
}
- 倒序遍歷
int[] arr = {1, 4, 7};
for(int i=arr.length- 1; i>= 0; i--){
System.out.println(arr[i]);//arr[2], arr[1], arr[0]
}
- 增強版for迴圈遍歷
int[] arr = {1, 4, 7};
// a表示每次迴圈從陣列中取出的那個元素,arr表示要遍歷的陣列
for(int a: arr){
System.out.println(a);
}
1.7.6陣列的排序
- 自帶排序
int[] arr = {3,6,9,2,5,8,1,4,7};
// Arrays.sort(T[] arr) 預設按照升序(從小到大)來排序的
java.util.Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//列印排序後的陣列,[1, 2, 3, 4, 5, 6, 7, 8, 9]
- 氣泡排序(筆試)
int[] arr = {3,6,9,2,5,8,1,4,7};
for(int i=0; i<arr.length-1; i++){ //控制趟數
for(int j=0; j<arr.length-1-i; j++){ //控制每趟的次數
//如果當前元素比後一個元素大,則交換位置
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));//列印排序後的陣列
1.7.7陣列的工具類
Java中提供了java.util.Arrays工具類,可以對陣列進行排序、檢索、轉換、輸出等操作。
Arrays.sort(arr); //對陣列進行排序
int index = Arrays.binarySearch(arr, key); //對陣列進行二分查詢,注:陣列中的元素一定是升序的
String str = Arrays.toString(arr); //將陣列轉換為字串
int[] newArr = Arrays.copyOf(arr, len); //擴容/縮容 陣列
1.8方法
1.8.1方法的簡介
方法也稱為函式/過程,封裝的一段特定的邏輯功能、有名字的程式碼塊。
方法可以使程式結構清晰、便於程式碼的重複使用。
1.8.2方法的定義
語法結構:
修飾符 返回值型別 方法名 ( [引數型別 引數名1, 引數型別 引數名2, ...]) {
方法體
[return返回值;]
}
上述程式碼的語法格式具體說明如下:
- 修飾符:用於限定方法的宣告,常見的有訪問控制修飾符、靜態修飾符、最終修飾符 等等。
- 返回值型別:用於限定方法返回值的資料型別,為了告訴呼叫者知道要用什麼型別來接收返回結果。
- 引數型別:用於限定呼叫方法時傳入引數的資料型別。
- 引數名:是一個變數,用於接收呼叫方法時傳入的資料。
- return 關鍵字:用於結束方法以及返回方法指定型別的值。
- 返回值:被return語句返回的資料,該值會返回給呼叫者。
方法中的“[引數型別 引數名1, 引數型別 引數名2, ...]”稱為引數列表,表示方法在呼叫時需要接收的引數,如果方法不需要接收任何引數,則引數列表為空,即()括號內不寫任何內容。
如果方法中沒有返回值,那麼返回值型別要宣告為void,方法中的return語句可以省略。
例如:
//無返回值無引數的方法
public static void sayHi() {
System.out.println("Hi");
}
//有返回值有引數的方法
public static int sum(int a, int b) {
int result = a + b;
return result;
}
//封裝氣泡排序演算法,方便重複呼叫
public static void bubbleSort(int[] arr) {
for(int i=0; i<arr.length-1; i++){ //控制趟數
for(int j=0; j<arr.length-1-i; j++){ //控制每趟的次數
//如果當前元素比後一個元素大,則交換位置
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
- 什麼時候方法要定義引數?
當方法中要使用到的資料,但是又不能在方法中寫死,那麼這時就可以把這些資料先定義為方法的引數,讓呼叫者在呼叫方法時再具體傳遞過來,引數可以使得方法變得更加靈活。
- 什麼時候方法要定義具體返回值型別?
當方法中邏輯計算完成之後,要返回計算的結果給呼叫者時,那麼就得定義具體的返回值型別。
1.8.3方法的呼叫
- 無參無返回值方法的呼叫
方法名();
System.out.println();
- 有參無返回值方法的呼叫
方法名(引數值..);
System.out.println(250);
- 無參有返回值方法的呼叫
資料型別 變數名 = 方法名();
double num= Math.random();
- 有參有返回值方法的呼叫
資料型別 變數名 = 方法名(引數值..);
double sqrt= Math.sqrt(4);
good luck!
- &和&&的區別?