1.java 基本資料型別、運算子、控制語句、方法和遞迴
1.基本資料型別
Java是一種強型別語言,每個變數都必須宣告其資料型別。 Java的資料型別可分為兩大類:基本資料型別(primitive data type)和引用資料型別(reference data type)。
Java中定義了3類8種基本資料型別
(1)整形(byte、short、int、long)
整型用於表示沒有小數部分的數值,它允許是負數。
Java 語言整型常量的四種表示形式
-
十進位制整數,如:99, -500, 0
-
八進位制整數,要求以 0 開頭,如:015
-
十六進位制數,要求 0x 或 0X 開頭,如:0x15
-
二進位制數,要求0b或0B開頭,如:0b01110011
注意:Java語言的整型常數預設為int型,宣告long型常量可以後加‘l’或‘ L ’,一般加‘L’。
(2)浮點型(float、double)。
float型別又被稱作單精度型別,尾數可以精確到7位有效數字,double表示這種型別的數值精度約是float型別的兩倍,又被稱作雙精度型別,絕大部分應用程式都採用double型別。浮點型常量預設型別也是double。
Java浮點型別常量有兩種表示形式
-
十進位制數形式,例如:3.14 314.0 0.314
-
科學記數法形式,如314e2 314E2 314E-2
注意:Java語言的浮點型常數預設為double型,宣告float型別的數值有一個字尾F 。
由於精度問題,實際使用時應該儘量避免兩個浮點數進行比較,同時如果需要進行沒有誤差的精確數字進行計算,可以使用java.math包中的BigInteger和BigDecimal類。以BigInteger為例,BigDecimal同理:
import java.math.BigDecimal; public class Main { public static void main(String[] args) { BigDecimal bd = BigDecimal.valueOf(1.0); bd = bd.subtract(BigDecimal.valueOf(0.1)); bd = bd.subtract(BigDecimal.valueOf(0.1)); bd = bd.subtract(BigDecimal.valueOf(0.1)); bd = bd.subtract(BigDecimal.valueOf(0.1)); bd = bd.subtract(BigDecimal.valueOf(0.1)); System.out.println(bd);//0.5 System.out.println(1.0 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1);//0.5000000000000001 } }
(3)字元型(char)
字元型在記憶體中佔2個位元組,在Java中使用單引號來表示字元常量。
char 型別用來表示在Unicode編碼表中的字元。Unicode具有從0到65535之間的編碼,他們通常用從’\u0000’到’\uFFFF’之間的十六進位制值來表示(字首為u表示Unicode)。
Java 語言中還允許使用轉義字元 ‘\’ 來將其後的字元轉變為其它的含義。常見轉義字元:
(4)布林型(boolean)
boolean型別有兩個常量值,true和false,在記憶體中佔一位(注意:不是一個位元組)。
一般不寫成if(flag == true)而是寫成if(flag)
2.運算子
注意:右移一位除以2(整除),左移一位乘以2。
&和&&的區別:
-
&和&&都可以用作邏輯與的運算子,表示邏輯與(and),當運算子兩邊的表示式的結果都為true時,整個運算結果才為true,否則,只要有一方為false,則結果為false。
-
&&還具有短路的功能,即如果第一個表示式為false,則不再計算第二個表示式,例如,對於if(str != null && !str.equals(“”))表示式,當str為null時,後面的表示式不會執行,所以不會出現NullPointerException如果將&&改為&,則會丟擲NullPointerException異常。If(x==33 & ++y>0) y會增長,If(x==33 && ++y>0)不會增長
-
&還可以用作位運算子,當&操作符兩邊的表示式不是boolean型別時,&表示按位與操作,我們通常使用0x0f來與一個整數進行&運算,來獲取該整數的最低4個bit位,例如,0x31 & 0x0f的結果為0x01
運算子優先順序問題:
1.沒必要知道,需要的時候,使用()表示運算先後順序,使程式可讀性強。
2.邏輯與、邏輯或、邏輯非的優先順序一定要熟悉!(邏輯非>邏輯與>邏輯或)。
如:a||b&&c的運算結果是:a||(b&&c),而不是(a||b)&&c
(重點)型別轉化問題:
1.自動型別轉換:
自動轉換按從低到高的順序轉換。不同型別資料間的優先關係如下:
低--------------------------------------------->高
byte,short,char-> int -> long -> float -> double
運算中,不同型別的資料先轉化為同一型別,然後進行運算,轉換規則如下:
運算元1型別 |
運算元2型別 |
轉換後的型別 |
byte、short、char |
int |
int |
byte、short、char、int |
long |
long |
byte、short、char、int、long |
float |
float |
byte、short、char、int、long、float |
double |
double |
2.強制型別轉換:
強制轉換的格式是在需要轉型的資料前加上“( )”,然後在括號內加入需要轉化的資料型別。有的資料經過轉型運算後,精度會丟失。
double x = 3.14;
int nx = (int)x; //值為3
char c = 'a';
int d = c+1;
注意:
1.當將一種型別強制轉換成另一種型別,而又超出了目標型別的表數範圍,就會被截斷成為一個完全不同的值。
int x = 300;
byte bx = (byte)x; //值為44
2.不能在布林型別和任何數值型別之間做強制型別轉換。
3.控制語句
選擇結構(if 和switch)
import java.util.Scanner;
public class TestIf {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("please input your score");
int x = sc.nextInt();
if(x<60) {
System.out.println("D");
}else if(x<75) {
System.out.println("C");
}else if(x<85) {
System.out.println("B");
}else {
System.out.println("A");
}
}
}
switch基本不用,懶得寫了
switch (表示式) {
case 值1:
語句序列1;
[break];
case 值2:
語句序列2;
[break];
… … … … …
[default:
預設語句;]
}
迴圈結構(while do-while for)注意break和continue
for迴圈
//計算0~100的和
public class Demo {
public static void main(String[] args) {
int sum = 0;
for(int i=0;i<=100;i++) {
sum += i;
}
System.out.println(sum);
}
}
while迴圈
//計算0~100的和
public class Demo {
public static void main(String[] args) {
int i = 0;
int sum = 0;
while(i <= 100) {
sum += i;
i++;
}
System.out.println(sum);
}
}
do-while
//計算0~100的和
public class Demo {
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum += i;
i++;
}while(i <= 100);
System.out.println(sum);
}
}
4.方法(函式)
方法的過載(overload):
過載的方法,實際是完全不同的方法,只是名稱相同而已!
構成方法過載的條件:
- 不同的含義:形參型別、形參個數、形參順序(首先要型別不同)不同
- 只有返回值不同不構成方法的過載
- 只有形參的名稱不同,不構成方法的過載
public class Demo {
public static void main(String[] args) {
System.out.println(add(3, 5));// 8
System.out.println(add(3, 5, 10));// 18
System.out.println(add(3.0, 5));// 8.0
System.out.println(add(3, 5.0));// 8.0
// 我們已經見過的方法的過載
System.out.println();// 0個引數
System.out.println(1);// 引數是1個int
System.out.println(3.0);// 引數是1個double
}
/** 求和的方法 */
public static int add(int n1, int n2) {
int sum = n1 + n2;
return sum;
}
// 方法名相同,引數個數不同,構成過載
public static int add(int n1, int n2, int n3) {
int sum = n1 + n2 + n3;
return sum;
}
// 方法名相同,引數型別不同,構成過載
public static double add(double n1, int n2) {
double sum = n1 + n2;
return sum;
}
// 方法名相同,引數順序不同,構成過載
public static double add(int n1, double n2) {
double sum = n1 + n2;
return sum;
}
//編譯錯誤:只有返回值不同,不構成方法的過載
public static double add(int n1, int n2) {
double sum = n1 + n2;
return sum;
}
//編譯錯誤:只有引數名稱不同,不構成方法的過載
public static int add(int n2, int n1) {
double sum = n1 + n2;
return sum;
}
}
遞迴:
遞迴的基本思想就是“自己呼叫自己”,一個使用遞迴技術的方法將會直接或者間接的呼叫自己。
遞迴結構包括兩個部分:
1.定義遞迴頭:什麼時候不呼叫自身方法,也就是遞迴的結束條件。如果沒有頭,將陷入死迴圈。
2.遞迴體:什麼時候需要呼叫自身方法。
//計算n的階乘
public class Demo {
public static void main(String[] args) {
System.out.println(factorial(10));
}
public static long factorial(int n) {
if(n == 1) {//遞迴頭
return 1;
}else {
return n*factorial(n-1); //遞迴體
}
}
}
利用遞迴可以用簡單的程式來解決一些複雜的問題。比如:斐波那契數列的計算、漢諾塔、快排等問題。但是遞迴呼叫會佔用大量的系統堆疊,記憶體耗用多,在遞迴呼叫層次多時速度要比迴圈慢的多,所以在使用遞迴時要慎重。