數據類型
在java中一共有8種基本類型,其中有4種整型,2種浮點類型,1種字符類型, 1種布爾類型。
- 整型
整型用於表示沒有小數部分的數值,允許是負數。
- int 4 字節 -2 147 483 648 ~ 2 147 483 647 (剛剛超過20億)
- short 2 字節 -32 768 ~ 32 767
- long 8 字節 -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807
- byte 1 字節 -128 ~ 127
- 浮點類型
浮點類型用於表示有小數部分的數值。
- float 4 字節 大約 +/- 3.402 823 47E+38F (有效位數6~7位)
- double 8 字節 大約 +/- 1.797 693 134 862 315 70E+308 (有效位數為15位)
float類型的數值有一個後綴F或f(3.14F), 沒有後綴F的浮點數值(3.14)總是默認位double類型。
浮點類型中有三個特殊的浮點數值表示溢出和出錯的情況:
- 正無窮大 (Double.POSITIVE_INFINITY),
- 負無窮大 (Double.NEGATIVE_INFINITY),
- NaN 非數字 (Double.NaN)
- char 類型
用於表示Unicode編碼的代碼單元, 在java種,char類型描述了UTF-16編碼種的一個代碼單元。
建議不要在代碼種使用char類型,最好將字符串作為抽象數據類型處理。 - boolean類型
boolean類型有兩個值: false 和 true,用來判定邏輯條件。整型值和布爾值之間不能進行相互轉換。
變量
- 申明變量
在java中每個變量都有一個類型,在申明變量時,先指定變量類型,然後是變量名。
double salary;
int vacationDays;
long earthPopulation;
boolean done;
- 變量初始化
聲明變量之後,必須用賦值語句對變量進行顯示初始化,使用未初始化的變量值,java編譯器會報錯。
- 對已聲明的變量進行初始化賦值
int vacationDays;
vacationDays = 12;
- 聲明變量和初始化在一行中
int vacationDays = 12;
double salary = 65000.0;
常量
使用關鍵字final指示常量,表示這個變量只能被賦值一次,之後就不能再更改了,習慣上常量名使用全大寫。
- 使用final在類方法中定義常量
public class Constants
{
public static void main(String[] args)
{
final double CM_PRE_INCH = 2.54;
double paperWidth = 8.5;
double paperHeight = 11;
System.out.println("Paper size in centimeters: " + paperWidth * CM_PRE_INCH + " by " + paperHeight * CM_PRE_INCH);
}
}
- 使用static final在類中定義類常量
public class Constants2
{
public static final double CM_PRE_INCH = 2.54;
public static void main(String[] args)
{
double paperWidth = 8.5;
double paperHeight = 11;
System.out.println("Paper size in centimeters: " + paperWidth * CM_PRE_INCH + " by " + paperHeight * CM_PRE_INCH);
}
}
枚舉類型
變量的取值在一個有限額集合內時就可以自定義枚舉類型來聲明變量。
// 自定義枚舉類型
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
// 聲明枚舉變量, 只能為Size中的某個值,或者null
Size s = Size.MEDIUM;
運算符
- 算術運算符 + - * /
- 當參與/運算的兩個操作數都是整數時,表示整數除法;否則表示浮點除法。
- 整數的求餘操作用%表示。
- 數學函數
使用Math類中的方法進行數學計算。
// 計算平方根
double x = 4;
double y = Math.sqrt(x);
System.out.println(y); // prints 2.0
// 數學常量
Math.PI
Math.E
- 數值類型之間的轉換
當用一個二元運算符連接兩個值時,先要將兩個操作數轉換為同一種類型,然後再進行計算。
- 如果兩個操作數中有一個是double類型,另一個操作數就會轉換為double類型。
- 否則,如果其中一個操作數是float類型,另一個操作數將會轉換為float類型。
- 否則,如果其中一個操作數是long類型,另一個操作數將會被轉換為long類型。
- 否則,兩個操作數抖將被轉換為int類型。
- 強制類型轉換
- 將浮點數轉換為整數
// 捨去浮點位
double x = 9.997;
int nx = (int) x; // prints 9
// 使用四捨五入
double x = 9.997;
int nx = (int) Math.round(x); // prints 10;
- 結合賦值與自增自減運算符
- 在賦值中使用二元運算符
x += 4;
// 等價於
x = x + 4;
- 自增自減
int m = 7;
int n = 7;
int a = 2 * ++m; // a is 16, m is 8
int b = 2 * n++; // b is 14, n is 8
- 關係和布爾運算符
- 關係運算符
相等: ==
不等: !=
小於: <
大於: >
小於等於: <=
大於等於: >= - 布爾運算符
邏輯與運算符:&&
邏輯或運算符:|| - 三元操作符 ?:
x < y ? x : y
- 位運算符
位與:&
位或:|
異或:^
取反:~
左移:<<
右移:>> - 括號與運算符優先級
如果不使用括號,就按照給出的運算符優先級次序進行計算,同一個級別的運算符按照從左到右的次序進行計算(但右結合運算符除外)
a && b || c 等價於 (a && b) || c
a += b += c 等價於 a += (b += c)
字符串
java字符串就是Unicode字符序列。java沒有字符串類型,而是在標準類庫中提供了一個預定義類String。每個用雙引號括起來的字符串都是String類型的一個實例。
String e = ""; // empty string
String greeting = "Hello";
- 子串
String greeting = "Hello";
String s = greeting.substring(0, 3); // s is "Hel"
- 拼接
String expletive = "Expletive";
String PG13 = "deleted";
String message = expletive + PG13; // message is "Expletivedeleted"
int age = 13;
String rating = "PG" + age; // rating is "PG13"
String all = String.join(" / ", "S", "M", "L", "XL"); // all is "S / M / L / XL"
String repeated = "java".repeat(3); // repeated is "JavaJavaJava"
- 不可變字符串
String類沒有提供修改字符串中某個字符的方法, String類型對象被稱為是不可變的。
// 通過拼接替換字符串
String greeting = "Hello";
greeting = greeting.substring(0,3) + "p!"; // greeting is "Help!"
- 檢測字符串是否相等
不要使用 == 檢測字符串相等,因為 == 只能確定兩個字符串是否存放在同一個位置上。
String s = "s";
String t = "t";
s.equals(t); // false
String greeting = "Hello";
"Hello".equals(greeting); // true;
// 不區分大小寫進行比較
"Hello".equalsIgnoreCase("hello"); // true;
- 空串與Null串
空串""是長度位0的字符串, 檢測字符串為空的方法:
if(str.length() == 0) 或 if(str.equals(""))
null表示目前沒有任何對象與該變量關聯,檢測一個字符串是否位null:
if(str == null)
檢測一個字符串既不是null, 也不是空串:
if(str != null && str.length() != 0)
- 構建字符串
如果需要用許多小段的字符串構建一個字符串則使用字符串構建器更高效
StringBuilder builder = new StringBuilder();
builder.append(ch); // appends a single character
builder.append(str) // appends a string
String completedString = builder.toString(); // 構建完成時,調用toString方法得到字符串對象
輸入與輸出
- 讀取輸入
// 構造與標準輸入流System.in 關聯的Scanner對象
Scanner in = new Scanner(System.in);
System.out.print("What is your name? ");
// 讀取一行輸入
String name = in.nextLine();
// 讀取一個單詞
String firstName = in.next();
System.out.print("How old are you? ");
// 讀取一個整數
int age = in.nextInt();
// 使用Console類讀取密碼
Console cons = System.console();
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");
- 格式化輸出
double x = 10000.0 / 3.0;
System.out.print(x); // 3333.3333333333335
System.out.printf("%8.2f", x) // 3333.33
// 提供多個參數
System.out.printf("Hello, %s. Next year, you'll be %d", name, age);
// 打印時間
System.out.printf("%tc", new Date());
格式説明符:
- d 十進制整數
- x 十六進制整數
- f 定點浮點數
- e 指數浮點數
- s 字符串
- c 字符
- tx 日期時間
- 文件輸入與輸出
// 讀入文件
Scanner in = new Scanner(Path.of("myfile.txt"), StandardCharsets.UFT_8);
// 寫入文件
PrintWriter out = new PrintWriter("myfile.txt", StandardCharsets.UFT_8);
控制流程
- 塊作用域
塊是由若干條java語句組成的語句,並用一對大括號括起來。
- 塊確定了變量的作用域
- 一個塊可以嵌套在另一個塊中
- 不能在嵌套的兩個塊中聲明同名的變量。
- 條件語句
- if 語句: if (condition) statement
- if else 語句: if(condition) statement1 else statement2
- if else if 語句: if(condition1) statement1 else if(condition2) statement2
- 循環語句
- while (condition) statement
- do statement while (condition)
- for (int i = 1; i <= 10; i++) System.out.println(i);
- switch 語句
case 標籤可以是以下類型:
- char, byte, short 或 int 的常量表達式
- 枚舉常量
- 字符串字面量
Scanner in = new Scanner(System.in);
System.out.print("Select an option (1, 2, 3, 4) ");
int choice = in.nextInt();
switch (choice) {
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
default:
// bad input
...
break;
}
- 中斷控制流程語句
- break 語句
用於跳出當前循環,或者跳到指定的label
while (year <= 100) {
balance += payment;
double interest = balance * interestRate / 100;
balance += interest;
if (balance >= goal) break;
years++;
}
- continue 語句
用於跳過本次循環,到循環首部繼續進行下一次循環
Scanner in = new Scanner(System.in);
for (count = 1; count <= 100; count++)
{
System.out.print("Enter a number, -1 to quit:");
n = in.netInt();
if(n < 0) continue;
sum += n;
}
大數
如果基本的整數和浮點數精度不能夠滿足需求,那麼可以使用java.math包中兩個類:BigInteger 和 BigDecimal
- valueOf 將普通數值轉化為大數
BigInteger a = BigInteger.valueOf(100);
- new BigInteger 將字符串類型的參數轉換為大數
BigInteger reallyBig = new BigInteger("2222322343454545656565676767676700")
- 大數運算: add, subtract, multiply, divide, mod, sqrt, compareTo
// 使用add 方法進行求和運算
BigInteger c = a.add(b); // c = a + b;
// 使用multiply 方法進行乘法運算
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2))); // d = c * (b+2)
數組
數組是一種數據結構,用來存儲同一類型值的集合。
- 聲明數組
// 聲明整型數組 a
int[] a;
// 聲明並初始化一個可以存儲100個整數的數組
int[] a = new int[100];
var a = new int[100];
// 創建數組並同時提供初始值
int[] smallPrimes = {2, 3, 5, 7, 11, 13};
String[] authors = {
"James Gosling",
"Bill Joy",
"Guy Steele",
};
//使用匿名數組重新初始化變量
smallPrimes = new int[] {17, 19, 23, 29, 31, 37};
// 創建長度為0的數組
int[] a = new int[0];
int[] b = new int[] {};
- 訪問數組元素
創建一個數字數組時,所有元素都初始化為0, boolean數組的元素會初始化為false, 對象數組的元素則初始化為一個特殊值null,
表示這些元素還未放任何對象。
- 通過for循環訪問數組元素
int[] a = new int[100];
for (int i = 0; i < 100; i++){
a[i] = i; // fill the array with numbers 0 to 99
}
// 將字符串數組初始化未空串
String[] names = new String[10];
for (int i = 0; i < 10; i++) names[i] = "";
// 使用array.length 獲得數組中元素個數
int[] a = new int[100];
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
- for each 循環訪問數組
int[] a = {1, 2, 3, 4, 5};
for (int element : a) {
System.out.println(element);
}
- 數組拷貝
- 兩個數組變量引用同一個數組
int[] smallPrimes = {17, 19, 23, 29, 31, 37};
int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12; // now smallPrimes[5] also 12
- 拷貝數組的值到新數組中
int[] luckyNumbers = {17, 19, 23, 29, 31, 37};
// 實現數組值的全部複製
int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);
// 擴容數組
luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);
// 裁切數組
luckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length-2);
- 命令行參數
每一個java應用程序都有一個帶String arg[]參數的main方法,其接受一個字符串數組,也就是命令行上指定的參數。
public class Message
{
public static void main(String[] args)
{
if (args.length == 0 || args[0].equals("-h"))
{
System.out.print("Hello,")
}
else if (args[0].equals("-g"))
{
System.out.print("Goodbye,")
}
// print other command line arguments
for (int i = 1; i < args.length; i++)
{
System.out.print(" " + args[i]);
}
System.out.println("!");
}
}
=> java Message -g cruel world // print: Goodbye, cruel world!
- 數組常用靜態方法
- static String toString(xxx[] a) 返回包含a中元素的一個字符串,如"[1, 2, 3, 4]"
- static void sort(xxx[] a) 使用優化的快速排序算法對數組進行排序
- static xxx[] copyOf(xxx[] a, int end) 返回與a類型相同的一個數組
- static xxx[] copyOfRange(xxx[] a, int start, in end) 返回從數組索引start開始到end結束,不包括end的新數組。
- static void fill(xxx[] a, xxx v) 將數組的所有數據元素設置為v
- static boolean equals(xxx[] a, xxx[] b) 如果兩個數組大小相同,並且下標相同的元素都對應相等,返回true。
- static int binarySearch(xxx[] a, xxx v) 使用二分查找算法在有序數組中查找值v,如果找到值v,則返回相應的下標,否則返回一個負數值r。
- 多維數組
- 聲明和初始化二維數組
double[][] balances;
balances = new double[10][10];
int[][] magicSquare = {
{16, 3, 2, 13},
{5, 10, 11, 8},
{9, 6, 7, 12},
{4, 15, 14, 1}
};
- 訪問二維數組
// 通過下標訪問
int a = magicSquare[1][2];
// for each 循環
for (double[] row : a) {
for (double value : row){
// do something with value
}
}
// 打印二維數組內容
System.out.println(Arrays.deepToString(a));