文章目錄
- 引言
- 什么是JAVA
- 第一個JAVA程式
- 結果
- JAVA的資料型別
- 內置資料型別
- 參考資料型別
- 內置資料型別
- 整型
- 浮點型
- 字符型
- 布爾型
- 參考資料型別
- 基礎型別轉換
- 自動型別轉換
- 強制型別轉換
- JAVA符號
- 算數運算子
- 關系運算子
- 邏輯運算子
- 補充
- JAVA邏輯判斷
- if / else
- switch case
- JAVA回圈
- for回圈
- while回圈
- break
- continue
- do while回圈
- 判斷與回圈的應用
- 求最大公因數
- 求100以內的素數
- 不死神兔
- 水仙花數
- 99乘法表
- 求Pi的值
- JAVA函式
- 格式
- 作用域
- void關鍵字
- 函式呼叫其他函式
- JAVA陣列
- 創建陣列
- 訪問陣列元素
- 遍歷陣列
- 陣列與函式
- 將陣列作為引數傳入函式
- 將陣列作為回傳值輸出
- 多維陣列
- 小案例 Tic-Tac-Toe (井字棋)
- 案例2,列印二維陣列初始值
- JAVA類與物件
- 物件創建
- 構造方法
- 無參構造
- 有參構造
- 注意
- 物件方法
- this關鍵字
- 方法多載Overload
- 物件封裝
- 物件繼承
- 介紹
- 多型
- 向上轉型
- 向下轉型
- instanceof關鍵字
- super關鍵字
- 物件是參考型別
- 包裝類
- JAVA字串
- 常用方法
- JAVA修飾符
- static
- 靜態方法
- 靜態代碼塊
- 靜態類
- final
- 最終類
- 最終變數
- 最終方法
- 物件常量
- abstract
- 抽象類
- 抽象方法
- JAVA介面
- 介紹
- interface關鍵字
- 注意
- 補充
- 案例
- JAVA內部類
- 成員內部類
- 靜態內部類
- 區域內部類
- 匿名內部類
- JAVA泛型
- 泛型方法
- 泛型類
- 泛型介面
- 通配符
- JAVA集合
- Collection介面
- List介面
- ArrayList
- LinkedList
- Set介面
- HashSet
- TreeSet
- Map介面
- Map遍歷
- HashMap
- TreeMap
- JAVA常用類
- Arrays類
- Date和Calendar類
- Date
- Calendar
- JAVA例外處理
- 常見例外
- 捕獲例外
- Throws 關鍵字
- 自定義例外類
- JAVA IO處理
- 流的概念
- 流的分類
- 位元組流
- 字符流
- 流的使用
- 位元組流使用
- 物件流與序列化
- 字符流使用
- 字符流讀取緩沖流
- 檔案夾操作
- FileFilter介面
- Properties
- 參考文獻
- FileFilter介面
- Properties
- 參考文獻
引言
學習一門編程語言不是一件難事,在本書的前言我要鄭重強調一下這件事,學習如逆水行舟,不進則退;只要大家堅持,相信最后定會有所識訓,本書作為一本入門的工具書,會側重講解JAVA的基礎知識,旨在引導讀者進入JAVA的學習大門,
什么是JAVA
JAVA是一種面向物件的高階編程語言,在JAVA中有句老話:萬物皆物件,對于java的介紹我參考百科的一些解釋,(Java具有簡單性、面向物件、分布式、健壯性、安全性、平臺獨立與可移植性、多執行緒、動態性等特點 [2] ,Java可以撰寫桌面應用程式、Web應用程式、分布式系統和嵌入式系統應用程式等)
第一個JAVA程式
由于JAVA是一門面向物件的語言,在運行程式時我們需要單獨建立一個類物件,在此類物件的main()函式中運行,廢話不多說,直接上代碼
public class hello_world
{
public static void main(String[] args)
{
//這樣我們就創立好了第一個程式的框架
//在main函式里面,我們就可以書寫一些需要的指令
}
}
作為編程界的慣例,第一個程式當然是在console里面列印"Hello World"
public class hello_world
{
public static void main(String[] args)
{
System.out.println("hello world");
}
}
System.out.println() 是一條將程式中的資料列印在控制臺,也就是console中的指令
在System.out.println后面有一對括號,在這個里面我們要傳入想要列印在console中的內容,即函式的引數
因為要將”hello world“轉化為計算機能看懂的語言,所以我們需要在"hello world"外加上雙引號,將其轉化為字串型別
這樣計算機就能讀懂我們的語言,從而輸出我們的指令,
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pfoSMW1z-1613061611808)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210128115153341.png)]
JAVA的資料型別
當我們運行JAVA程式時,我們會進行一系列的數學計算,此時擁有存貯資料的變數就尤為重要,在JAVA中為了擁有存盤資料的變數,我們往往需要在記憶體中開辟一道空間,例如:
//在編輯器中的代碼變數
int x =5;
int y =6;
//在記憶體中存盤的變數資料, 變數名稱我們可以自定義
JAVA的資料型別可以分為2大類
-
內置資料型別
-
參考資料型別
內置資料型別
Java 的內置資料型別一共有8種,8種中又可以分為4種,
- 整型: byte, short, int, long
- 浮點型: float, double
- 字符型: char
- 布爾型: boolean
整型
整型顧名思義,它是用來存盤整數的
雖然byte, short, int和long都屬于整型,但它們之間還是各有差異因為各自的取值不同,
| 資料型別 | 資料范圍 | 資料大小(bit /位) | 默認值 |
|---|---|---|---|
| byte | -128~127 (-2^7 ~(2^7)-1) | 1 byte= 8 bits | 0 |
| short | -32768~32767 (-2^15 ~(2^15)-1) | 2 bytes = 16 bits | 0 |
| int | -2^31 ~ (2^31)-1 | 4 bytes = 32 bits | 0 |
| long | -2^63 ~(2^63)-1 | 8 bytes = 64 bits | 0L |
一般情況下,我們使用int型別來定義整數,因為int的范圍足以滿足我們日常的需求
byte a =100;
short b = 10000;
int c = 100000;
long d =10000000;
浮點型
與整型恰好相反,浮點型是用來存盤小數的,浮點型分為float和double,兩者的區別在于精度,
| 資料型別 | 資料范圍 | 資料大小(bit /位) | 默認值 |
|---|---|---|---|
| float (單精度浮點型) | 1.4·10^-45 ~ 3.4·10^38 | 4 bytes = 32 bits | 0.0f |
| double(雙精度浮點型) | 4.9·10^-324 ~ 1.7·10^308 | 8 bytes = 64 bits | 0.0d |
雖然說浮點數可以表示小數,但是浮點數不能表示精確的數,例如貨幣,如果需要表示精確的數,需要借助其他java類例如Big Decimal來實作,例子: 1.40* 165 = 231 但是 計算機給出的計算是230.999999999997
通常浮點數在未宣告的前提下都是double型別,
float f1 = 234.5f;
double d1 = 123.4;
字符型
char型別是一個單一的16位Unicode字符, 表示字符時用單引號,char的范圍是0~65535,大小為16 bits
| 資料型別 | 資料范圍 | 資料大小(bit /位) | 默認值 |
|---|---|---|---|
| char(字符) | 0~65535 | 2 bytes = 16 bits | ‘u0000’ |
對char變數賦值既可以使用數字,也可以使用字符,char可以存盤任何字符
public class test {
public static void main(String[] args) {
char a =65;
char b ='A';
System.out.println(a);
System.out.println(b);
}
}
結果
布爾型
布爾型別指true和false,boolean資料只表示1位資訊,可作為標志flag來記錄true或false
| 資料型別 | 資料范圍 | 資料大小(bit /位) | 默認值 |
|---|---|---|---|
| boolean | true / false | 1 bit | false |
參考資料型別
- 陣列
- 類與物件
- 字串
下面有一張圖來表示參考型別資料
這張圖上p1,p2,p3,p4作為類物件,當他們被創建時,他們實際上時作為指標指向一些資料
在本節參考型別暫時提一下,在后面的章節中會詳細解釋這些
基礎型別轉換
在運行程式時,我們有時需要將不同型別的資料轉化為同一型別
型別轉換又可分為自動型別轉換與強制型別轉換
自動型別轉換
自動轉換條件是轉換前資料型別的位數低于轉換后資料型別的位數
轉化程序中可能會有精度損失
byte , short , char 可自動轉化為int
int 可轉化為 long
long 可轉化為 float
float 可轉化為 double
public class test {
public static void main(String[] args) {
char a =65;
int b = a;
System.out.println(a);
System.out.println(b);
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uWyg1G64-1613061611811)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210128175039057.png)]
強制型別轉換
如果被轉化資料型別位數大于要轉化的資料型別的位數,此時需要用到強制型別轉換,注意Boolean型別不能被強制轉換
強制轉換格式
public class test {
public static void main(String[] args) {
char a ='A';
byte b = (byte)a; //強制將char型別轉化為byte型別
//其實將這些資料列印出來,也暗含了一層資料轉換
System.out.println(a);
System.out.println(b);
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Sf8WSxcn-1613061611813)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210128175841728.png)]
JAVA符號
既然JAVA作為一門計算機編程語言,它一定能像計算器一樣為我們做一些運算,所以在本章我們將講解JAVA的運算子號,
算數運算子
運算優先級和現實生活中一樣,括號( ) > * 或 % 或 / > + 或 -
| 符號 | 含義 | 例子 |
|---|---|---|
| = | 賦值 | int i =5; 把5賦值給i |
| + | 加號 | int i = (5+6); |
| - | 減號 | int j = (6-1); |
| * | 乘號 | int k = (7*8); |
| / | 取整 | int a = (7/8); |
| / | 除號 | double c = 7.0 /8; |
| % | 取余 | int b = (7%8); |
| // | 轉義字符 | 寫注釋用的 |
public class test {
public static void main(String[] args) {
int i = 5+6;
int j = 6-1;
int k = 7*8;
int a = 9 / 8;
double b = 9.0 / 8; //如果想用除法獲得小數,必須要用double型別的資料
int c = 9 % 8;
System.out.println("5+6 = "+i);
System.out.println("6-1 = "+j);
System.out.println("7*8 = "+k);
System.out.println("(整除)9/8 = "+a);
System.out.println("(除以)9.0/8 = "+b);
System.out.println("(取余)9%8 = "+c);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EfkgjWuS-1613061611814)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129202007447.png)]
//優先級測驗
public class test {
public static void main(String[] args) {
double a = (2+1)+3.0/5-6*7-(4/3);
System.out.println("(2+1)+3.0/5-6*7-(4/3) = "+a); //注意(4/3) 是取整,結果是1
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ACH71YxL-1613061611816)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129202931197.png)]
關系運算子
在運行程式時,我們需要對一些資料進行判斷,此時就需要關系運算子
關系運算子判斷后,回傳true 或 false
| 符號 | 含義 | 例子 |
|---|---|---|
| == | 等于 | (6 == 7) false |
| != | 不等于 | (6 != 7) true |
| > | 大于 | (6 > 7) false |
| < | 小于 | (6 < 7) true |
| <= | 小于或等于 | (6 <= 7) true |
| >= | 大于或等于 | (6 >= 7) false |
邏輯運算子
和電路圖中的邏輯門類似, 邏輯運算子就是
與, 或,非
A為true
B為false
| 符號 | 含義 | 例子 |
|---|---|---|
| && | 與,and,當左邊與右邊同時為true時回傳true | (A && B) false |
| || | 或, or, 左邊或右邊任意一個滿足即回傳false | (A||B) true |
| ! | 非,與所選的條件相反 | !(A||B) false |
補充
看別人的原始碼時有時會碰到以下的幾種符號
| 符號 | 含義 | 例子 |
|---|---|---|
| ++ | 加一 | a++; a的值加1 |
| – | 減一 | b–; b的值減1 |
| += | 加等于 | a += b; 意思是a= a + b; |
| -= | 減等于 | a -= b; 意思是 a = a -b; |
| /n | 換行 | “/n” |
| /t | 水平制表符 | 從左往右數8個空格 |
JAVA邏輯判斷
上文我們提到了邏輯運算子與關系運算子,這些符號會給我們回傳boolean 型別的資料 :true 或 false
true / false便是用在邏輯判斷中的
if / else
假如大家對其他語言,例如python有所了解, 判斷通常會使用if else陳述句,格式如下
if(條件陳述句){
//執行的指令
}
else if(條件陳述句){
//執行的指令
}
//else指的是最終條件,即排除if與else if條件之后
else{
//執行的指令
}
例子
在這個例子里面會用到用戶輸入指令,Scanner
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //創建scanner物件,這樣就可以從控制臺輸入
System.out.print("a: ");
int a = input.nextInt(); //nextInt()指輸入的值是int型別資料,該方法是通過物件呼叫,后面會講
System.out.print("b: ");
int b = input.nextInt();
//比較a與b的大小
if(a>b) {
System.out.println("a大于b");
}
else if(a<b) {
System.out.println("a小于b");
}
else {
System.out.println("a等于b");
}
input.close();
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-j6heCkcD-1613061611817)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129210114533.png)]
除此之外,還有嵌套式的if else
if(a > b){
if(a > c){
//當a大于b 同時 a大于c時,列印"a is MAX"
System.out.println("a is MAX");
}
else{
System.out.println("b < a <c ");
}
}
switch case
switch case 類似于條件判斷,通過switch的判斷來選取對應的case,格式如下
switch(condition){
case value:
//action
break;
case value2:
//action
break;
default: //當case中的value沒有一個滿足condition時,default中的指令才會執行
//action
}
例子
//輸出輸入數字所對應的英文(1-9)
import java.util.Scanner;
public class switch{
public static void main(String[] args) {
System.out.print("NUM: ");
Scanner num = new Scanner(System.in);
int digit = num.nextInt();
String digitName; //String是字串型別,屬于參考資料型別,在后面有提到
switch (digit) {
case 1:
digitName = "one";
break;
case 2:
digitName = "two";
break;
case 3:
digitName = "three";
break;
case 4:
digitName = "four";
break;
case 5:
digitName = "five";
break;
case 6:
digitName = "six";
break;
case 7:
digitName = "seven";
break;
case 8:
digitName = "eight";
break;
case 9: digitName = "nine"; break; //有時為了節省空間,可以連在一起寫
default: digitName = "I cannot distinguish this number"; break;
}
System.out.print(digitName);
num.close();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MZpyKBrc-1613061611819)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101525956.png)]
每個case后面都跟有一個break,用于阻止case1中的action執行完畢后再執行case2的action
反例
import java.util.Scanner;
public class switch2{
public static void main(String[] args) {
System.out.print("NUM: ");
Scanner num = new Scanner(System.in);
int digit = num.nextInt();
String digitName;
switch (digit) {
case 1: digitName = "one"; break;
case 2: digitName = "two"; break;
case 3: digitName = "three"; break;
case 4: digitName = "four";
case 5: digitName = "five";
case 6: digitName = "six"; break;
case 7: digitName = "seven"; break;
case 8: digitName = "eight"; break;
case 9: digitName = "nine"; break;
default: digitName = "I cannot distinguish this number"; break;
}
System.out.print(digitName);
num.close();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hbcY1AyX-1613061611820)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101720253.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ggRlfTKu-1613061611821)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101740442.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DW41QtCF-1613061611822)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101843945.png)]
由于沒有在case 4和 case 5后面加上break, 無論輸入的是4還是5,最終給予digitName的賦值始終是 “six”;
直白點說,break就是用來阻止程式繼續向下運行的指令
JAVA回圈
學完邏輯判斷與基本的運算,接下來我們要了解一下java中的回圈,
java的回圈如同其他語言一樣,包含
- for回圈
- while回圈
- do while回圈
for回圈
結構
for(初始值;回圈結束條件;初始值變化){
//action
}
在for回圈中,初始值一般是我們自定義的,例子如下
//我們創造一個for回圈,這個回圈運行5次,每次列印我們定義的變數的值
for(int i=0;i<5;i++){
System.out.println(i);
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UxKmB9Ks-1613061611823)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130103416060.png)]
從輸出的結果可以看出,當i的值等于5時,條件回傳為false,回圈終止
while回圈
格式
//判斷條件指的是滿足這個條件時,程式回圈運行
while(判斷條件){
//action
}
例子
//與上面for回圈的案例類似
int i=0;
while(i <5) {
System.out.println(i);
i++; //前面計算符號補充部分有提及,i++指 i = i + 1
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-e0XuzCEk-1613061611824)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130104404416.png)]
如果對這個不太明白,下面有一幅圖可以解釋
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-at8b94pM-1613061611825)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130105844321.png)]
總共運行了5次,在第6次時條件判斷為false,所以回圈停止
break
while回圈還可以與之前switch case里面提到的break一起使用,例子如下
int i=0;
while(i < 7) {
//當i 等于 5 時,回圈中止
if(i == 5) {
break; //break的作用是中止回圈
}
System.out.println(i);
i++;
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SRjU0ohf-1613061611826)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130111831321.png)]
continue
與break對應的是continue,break是中止回圈
而continue是跳過這一輪回圈將要執行的陳述句,直接進入下一輪回圈,例子如下
public class test {
public static void main(String[] args) {
int i=0;
while(i <7) {
System.out.println(i);
i++;
//當i 等于 5時,跳過輸出這一輪的 "--------"
//由于i++放在前面,所以輸出i后, i的值+1, 即在第5輪,輸出i=4過后跳過輸出 "--------"
if(i == 5) {
continue;
}
System.out.println("--------");
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pjRHZxY4-1613061611827)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130112521021.png)]
do while回圈
格式
do{
//action
}while(判斷條件);
do while回圈和while回圈的區別是:無論條件為何,do while回圈都會將action部分執行一遍,例子如下
public class test {
public static void main(String[] args) {
int i=0;
do {
System.out.println(i);
i++;
}while(i<0);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LvRoK3o2-1613061611828)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130124327971.png)]
判斷與回圈的應用
前面幾章我們學習了java的運算子,邏輯判斷與回圈,這一章舉一些例子,靈活運用前面的知識
求最大公因數
題目:求出48與292的最大公因數與最小公倍數,
程式分析:使用輾轉相除法
public class LargestFactor {
public static void main(String[] args) {
int m =48;
int n = 292;
int a = m;
int b = n;
int r = a%b;
while (r!=0) {
a = b;
b = r;
r = a%b;
}
int divisor = b;
System.out.println("The Greatest Common Divisor:"+divisor);
System.out.println("The Lowest Common Multiple:"+(m*n)/divisor);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-S6scExTR-1613061611829)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130155438457.png)]
求100以內的素數
題目:輸出100以內的素數?
程式分析:素數是大于1的正整數,只能除以它本身與1
public class isprime {
public static void main(String[] args) {
for(int i=2; i<=100; i++) {
boolean isPrime = true;
for (int j=2; j<i; j++) {
if((i%j) == 0) {
isPrime = false;
break;
}
}
if(isPrime) {
System.out.println(i+" is prime");
}
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wZUo3rXp-1613061611829)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130143041470.png)]
不死神兔
題目:古典問題:有一對兔子,從出生后第3個月起都生一對兔子,小兔子長到第3個月后每個月又生一對兔子,假如兔子都不死,問每個月的兔子對數為多少(20個月內)?
程式分析:兔子的規律為數列1,1,2,3,5,8,13,21…(斐波那契數列)
public class Test{
public static void main(String[] args){
long a=1;
long b=1;
long c=0;
System.out.print(a+"\t"+b);
//for回圈用來計數
for(int i=3;i<=20;i++){
//a,b,c交換資料
c =a+b;
a =b;
b =c;
System.out.print(c+"\t");
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-URMRdTWP-1613061611830)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130140249510.png)]
水仙花數
題目:列印出1000以內的水仙花數,所謂的“水仙花數”是指一個三位數,其各位數字立方和等于該數本身,例如:152是一個“水仙花數”,因為153 =1的3次方+5的3次方+3的3次方,
程式分析:需要用到for回圈,每個數分解出個位,十位,百位
public class flower {
public static void main(String[] args) {
//水仙花數是三位數,從100開始,到1000結束
for(int i=100; i<1000; i++ ) {
//第一種獲取每位的方法
int a = i/100; //對i取整,獲取百位的數字
int b = (i-a*100)/10; // 減去1的百位上的數字,除以10,獲取十位的數字
int c = i-100*a-10*b; //個位就是排除十位與百位
//第二種獲取每位的方法
//int a = i/100;
//int b = (i%100)/10; //對i除以100取余,再通過10取整,獲得百位
//int c = (i%100)%10; //對i除以100取余,再通過10取余,獲得個位
int sum = a*a*a+b*b*b*b+c*c*c;
if (sum==i) {
System.out.println(i+"是水仙花數");
}
}
System.out.println("Finish");
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XXBkYWV8-1613061611831)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130133328919.png)]
99乘法表
題目:輸出9*9口訣
程式分析:嵌套式for回圈,注意換行
public class test {
public static void main(String[] args) {
for(int i=1;i<=9;i++) {
for(int j=1;j<=i;j++) {
System.out.print(j+"*"+i+"="+(i*j)+"\t");
}
System.out.println();
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eSlfSUmN-1613061611831)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130155506835.png)]
求Pi的值
題目:根據Gregory-Leibniz series, 我們可以計算Pi的值,要求算到第10000個級數
程式分析:Pi = (4/1) - (4/3) + (4/5) - (4/7) + (4/9) - (4/11) + (4/13) … 觀察發現規律:分母為奇數,偶數-1,
public class test {
public static void main(String[] args) {
double rst=0.0;
for(int i=1;i<=10000;i++){
//判斷是偶數還是奇數
if(i%2==1){
rst += 4.0/(2.0*i-1); //分母為奇數1,3,5,7……
}
else{
rst -= 4.0/(2*i-1);
}
}
System.out.println(rst);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EU9GcD7q-1613061611832)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130160022440.png)]
JAVA函式
函式,大家在初高中應該有所耳聞,例如f (x), f (x) 這個函式有名字f, 同時它也包含一個引數x,設定一個函式可以被我們連續呼叫,java或者說大部分主流的編程語言都繼承了數學中函式的特點,
在本書的前面幾章大家應該已經接觸到了函式,System.out的println(""),這個就是一個系統類的函式(方法)
我們可以將想要列印在console(控制臺)上的內容作為引數傳入此函式(方法),它就將內容呈現出來
格式
java的函式(在類物件中也可以叫做方法)格式
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bTA4Pg2Z-1613061611834)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130182507127.png)]
- 函式回傳值型別可以為任意資料型別,int, double, char, string等
- public static 都是修飾符,在后賣會講到
- return 的值型別一定要與定義函式時一致
在函式或方法中引數還有另外一個名字,形參;而我們傳入時的引數叫實參(實際的引數)
作用域
說到函式或方法,那一定要提及作用域,即我們創建的引數能夠用在那些范圍內
下面我們用一個例子來解釋
public class test {
public static void main(String[] args) {
int a = 8;
int b = 9;
int c = add(a,b); //當要呼叫方法時,直接寫該函式的名字與應該傳入的引數
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
public static int add(int i, int j) {
int a = i + j;
return a;
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EZnODs2e-1613061611835)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130184251449.png)]
在上面的例子中,main主函式中的a, b, c是實參;而add函式中的i, j, a都是形參
我們可以看出雖然在main函式與add函式中a都是我們的引數,但是兩者為什么都不沖突呢?
因為作用域的不同導致了兩者的不同,在add函式中定義的引數的作用域僅僅在add函式中,不超過add,而main函式中定義的引數的作用域也僅僅在main中,無法擴散到add函式中,
假如main函式想要與add函式交換引數,就必須通過形參和return,
void關鍵字
有心的小伙伴也許已經發現了我們的main函式為什么沒有回傳值,且是回傳值型別是void
void的英文意思是空,即什么也沒有
同理,用在函式上時,表示該函式接收引數但不需要有回傳值,這個函式就像一個方法一樣,如下
//寫一個比較大小的程式
public class test {
public static void main(String[] args) {
int a = 19;
int b = 79;
int c = 100;
MAX(a, b, c); //此時呼叫MAX方法,沒有回傳值
}
public static void MAX(int a, int b, int c) {
System.out.println("NUM: "+a+" "+b+" "+c);
int max = a;
if(a < b) {
max =b;
if(b < c) {
max = c;
}
}
System.out.println("MAX is "+max);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eQRe1Svh-1613061611836)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130190143049.png)]
函式呼叫其他函式
我們在一個函式中可以呼叫別的函式,例子如下
public class test {
public static void main(String[] args) {
int a = 19;
int b = 79;
int c = 100;
MAX(a, b, c);
}
public static void MAX(int a, int b, int c) {
System.out.println("NUM: "+a+" "+b+" "+c);
int max = a;
if(a < b) {
max =b;
if(b < c) {
max = c;
}
}
print(max); //直接輸入函式名與引數就可以使用該函式
}
//通過print函式我們把max的值列印出來
public static void print(int max) {
System.out.println("MAX is "+max);
}
}
JAVA陣列
上文提到了參考型別資料,在本章我將講解其中一個參考型別資料:陣列
對C語言或其他編程語言有所了解的伙伴應該聽說過陣列這個定義,陣列,顧名思義,是將一系列統一的資料放在一起的組合,比如我們想將 ‘h’,‘e’,‘l’,‘l’,‘o’ 這幾個字符放在一起之后再使用,此時我們就需要創建一個 字符型別的陣列,
為什么說陣列是參考型別的呢?
當我們創立一個陣列并賦予其值,并不是在記憶體中直接開辟含有這些資料的陣列,而是將陣列的指標指向這些資料,直白點說,陣列就像瀏覽器中的收藏夾,我們需要點擊哪個鏈接(資料)時,就打開這個收藏夾(陣列)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9hiEMme8-1613061611837)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129163522377.png)]
以char型別的陣列為例,接下來將介紹幾種創建陣列的方法
創建陣列
//宣告陣列變數
char[] words;
char words[];
//創建陣列的幾種方法
//1
//每一組括號前要先宣告陣列中存盤資料的型別
words = new char[5]; //在后面的括號中放的資料是我們所定義的陣列的大小
//2
words2 = new char[5] //與上一個差不多
//當然宣告與創建陣列可以放在一起
char[] word = new char[5];
//3
char[] words3 = {'h','e','l'.'l','o',};
當第1種和第2種陣列創建完畢后,默認內部的5個元素都為’\u0000’(char 型別的默認值);
當第3種陣列創建完畢后,默認的元素是初始化的那些元素
import java.util.Arrays;
public class test {
public static void main(String[] args) {
int[] words = new int[5];
char words2[] = new char[5];
char[] words3 = {'h','e','l','l','o'};
//由于陣列無法直接通過System.out.println列印出來,
//我們需要呼叫Arrays包中的toString()方法
System.out.println("words "+Arrays.toString(words));
System.out.println("words2 "+Arrays.toString(words2));
System.out.println("words3 "+Arrays.toString(words3));
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ougL3cAd-1613061611839)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129170236619.png)]
訪問陣列元素
創建陣列是為了儲存資料,所以我們應該要明白如何訪問/呼叫陣列中的元素
我們需要通過陣列的下標來訪問陣列中的元素
在計算機編程語言中,陣列下標幾乎都是從0開始(陣列中第一個元素),因為這樣可以方便計算機的指標讀取資料
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VPnPsy1p-1613061611840)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129172730705.png)]
所以陣列中第一個元素下標是0,第二個元素下標是1,依次類推,注意最后一個元素的下標必須是(陣列長度-1),因為元素下標是從0開始的,
public class array2{
public static void main(String[] args) {
double[] values = {2,3,4,5};
double one = values[0]; //注意獲取陣列中元素,接收的變數型別應與陣列一致
double two = values[1];
System.out.println(one);
System.out.println(two);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6IIEPOJg-1613061611840)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129173312581.png)]
有心的同學應該注意到了,我們存進去的元素是整數型別,為什么最后列印出來是double呢?
因為在存入double型別陣列中時,編譯器進行了自動型別轉換,將整型轉化為浮點double型別
遍歷陣列
為了讀取陣列中的元素,我們通常使用遍歷的方法
通過一組for回圈來獲取陣列中的每個元素
public class array2{
public static void main(String[] args) {
double[] values = {2,3,4,5};
//public int length;是java陣列中自帶的方法,用于回傳該陣列的長度
for(int i=0;i<values.length;i++) {
System.out.println(values[i]);
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mNk9DjfS-1613061611840)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129174548429.png)]
我們還可以使用for-each(也叫增強for)來遍歷陣列
for(type element : array){
System.out.println(element);
}
增強for允許我們在不訪問下標的情況下讀取陣列,十分方便
public class array2{
public static void main(String[] args) {
double[] values = {2,3,4,5};
for(double value: values) {
System.out.println(value);
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xbhNNukY-1613061611841)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129174548429.png)]
陣列與函式
我們可以把陣列作為一個回傳值或引數放在函式中
將陣列作為引數傳入函式
public class array2{
//add 將陣列作為引數傳入函式,回傳陣列中所有元素的和
public static double add(double[] values) {
double total = 0;
for (double element : values)
{
total = total + element;
}
return total;
}
public static void main(String[] args) {
double[] values = {2,3,4,5};
System.out.println(add(values));
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gzZI0CFL-1613061611842)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129184602683.png)]
將陣列作為回傳值輸出
import java.util.Arrays;
//將輸入陣列每個元素加1,并回傳
public class array2{
public static double[] add(double[] values) {
for(int i=0;i<values.length;i++) {
values[i] += 1;
}
return values;
}
public static void main(String[] args) {
double[] values = {2,3,4,5};
System.out.println(Arrays.toString(add(values)));
}
}
多維陣列
我們的現實世界是由多個維度所組成,一條線是一維, 一個平面是二維,我們所在的空間是三維
和現實世界類似,陣列也可以創造多個維度
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-26KDN6dx-1613061611843)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129185959447.png)]
創建二維陣列或多維陣列的方式與一維陣列類似
public class test {
public static void main(String[] args) {
int[][] num = new int[2][3]; //創建一個2行3列的二維陣列
num[0][0] = 1; //給第一行,第一列的元素賦值為1
num[1][0] = 2; //給第二行,第一列的元素賦值為2
//因為是二維陣列,通過兩個for回圈來遍歷列印
for(int i=0;i<num.length;i++) {
//num.length是獲取二維陣列的行數
for(int j=0;j<num[0].length;j++) {
//num[0].length是獲取第一行陣列的個數,即num二維陣列的列數
System.out.print(num[i][j]+" ");
}
System.out.println();
}
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DgaM6fUI-1613061611843)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129191554891.png)]
在本章中我們有運用到一個陣列的工具類, Arrays,在后面常用類中,我們會有詳細的解釋,
小案例 Tic-Tac-Toe (井字棋)
import java.util.Scanner;
public class TiTaTu{
public static void main(String[] args) {
//用二維陣列模擬棋盤, 0和1代表O和X
int [][] array = {
{0,1,0,1},
{1,0,0,1},
{1,1,1,1},
{0,1,0,1},
};
boolean rst_X = false;
boolean rst_O = false;
int numOfX_S = 0;
int numOfO_S = 0;
int numOfX_RS = 0;
int numOfO_RS = 0;
int k = array.length -1;
for(int n=0;n<array.length;n++) {
int numOfX_H =0;
int numOfO_H =0;
for(int m=0;m<array[n].length;m++) {
if(array[n][m] == 1) {
numOfX_H++;
if(numOfX_H == array.length ) {
rst_X = true;
}
}
else if(array[n][m] == 0){
numOfO_H++;
if(numOfO_H == array.length){
rst_O = true;
}
}
}
if(array[n][n] == 1) {
numOfX_S++;
if(numOfX_S == array.length ) {
rst_X = true;
}
}
else if(array[n][n] == 0) {
numOfO_S++;
if(numOfO_S == array.length ) {
rst_O = true;
}
}
//reverse diagonal line
if(array[n][k] == 1) {
numOfX_RS++;
if(numOfX_RS == array.length ) {
rst_X = true;
}
}
else if(array[n][k] == 0) {
numOfO_RS++;
if(numOfO_RS == array.length ) {
rst_O = true;
}
}
k--;
}
if(rst_X == true) {
System.out.print("X win");
}
else if(rst_O == true) {
System.out.print("O win");
}
else {
System.out.print("Equal");
}
}
}
案例2,列印二維陣列初始值
public class Print2DArray{
public static void PrintOut(int[][] array) {
for(int i=0; i<array.length;i++) {
for(int j=0;j<array[i].length;j++) {
System.out.printf("%3d", array[i][j]);
}
System.out.println();
}
}
public static void main(String[] args) {
int[][] a = new int[5][5];
PrintOut(a);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9gpzHDwx-1613061611845)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131235733815.png)]
JAVA類與物件
不知道大家以前有沒有聽說過這樣一句話“萬物皆物件”,這句話出自Think in Java,一本今典的java書籍,在java中,任何東西都可以被描述成一個類,且每個類都能被用來實體化物件;因為周圍的世界是由各種各樣的物件所構成,所以我們可以利用java來模擬我們周圍的世界,創建各種各樣的類例如:學生類,老師類,汽車類,飛機類,
物件創建
創建一個物件的前提是有這個物件的類,我們先創建一個Animal類
package Class_Study;
public class animal {
private int age; //private是修飾符,后面會講
public animal(){
//action 我們可以在這里添加一些指令
}
public animal(int num) {
age = num;
}
public void roar() {
System.out.println("I am yelling.");
}
}
擁有了animal這個類后,我們就可以實體化(創建)一個animal物件
animal Tom = new animal();
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5iOegIrB-1613061611846)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131105309311.png)]
以后要是想對animal物件進行一些操作,直接通過Tom呼叫animal的內部方法(長得像函式的東西)即可,
構造方法
在類中的函式統一稱作“方法”
有人也許注意到了在animal類中為什么還有與animal同名的方法呢?
這些方法叫做構造方法,也稱建構式,
無參構造
public animal(){ //public是修飾符
System.out.println("I am an animal."); //在無參構造方法里面,我們可以寫一些指令
}
像這一個構造方法,就是無參構造方法,當我們實體化物件時,可以不需要添加引數
animal Tom = new animal();
假如我們書寫的類中沒有寫構造方法,如下
package Class_Study;
public class animal {
public void roar() {
System.out.println("I am yelling.");
}
}
此時,編譯器會自動給我們加上一個無參構造方法,等同于這樣
package Class_Study;
public class animal {
public animal(){
}
public void roar() {
System.out.println("I am yelling.");
}
}
有參構造
有參構造方法就是在無參構造的基礎上增添了引數,方便我們將外部的引數傳遞給實體化的物件
我們第一個實體化物件的例子中除了有無參構造方法,還有有參構造方法
public animal(int num) {
age = num; //將外部的引數num賦值給物件內部的age
System.out.println("My age is "+ age); //將age的值輸出到控制臺上
}
因為是有參構造方法,我們實體化時可以加引數
int age = 3;
animal Tom = new animal(age);
//由于作用域的不同,我們在main函式中定義的age并不與animal物件中的age相沖突
注意
當我們既沒有寫無參構造也沒有寫有參構造時,編譯器會自動給我們加上一個無參構造方法,
但如果我們自己寫了有參構造方法或無參構造方法任意一個以后,編譯器就不會自動添加無參構造方法,
物件方法
上面也提到了,在類物件中函式叫做方法method, 除了叫法不同,各種功能與函式一致
package Class_Study;
public class animal {
private int age;
public animal(){
}
public animal(int num) {
age = num;
System.out.println("My age is "+ age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
在animal類中,roar就是物件方法,使用roar方法必須通過animal的實體化的物件來呼叫
public class animalTest {
public static void main(String[] args) {
animal Tom = new animal(3);
Tom.roar();
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pGFaF1y5-1613061611847)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131113112130.png)]
因為在實體化程序中使用了有參構造方法,有參構造方法中有一行指令是列印age: "System.out.println("My age is “+ age);” 所以在控制臺中出現 My age is 3
我們通過Tom來呼叫類方法
Tom.roar();
所以程式執行此方法,在控制臺中列印 “I am yelling”
this關鍵字
this關鍵字可以用于在本類中呼叫,本類方法或實體變數; 它也可以用于呼叫本類中其他構造方法;
this可以理解為當前物件
一個一個分析;
- 實體變數
當我們方法中的形參與類物件中的引數名字一樣時,使用this關鍵字可以避免運行時的error,如下
沒有使用this 關鍵字時
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
age = age;
}
public void printAge() {
System.out.println("My age is "+ age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
public class animalTest {
public static void main(String[] args) {
animal Tom = new animal(3);
Tom.printAge();
}
}
此時的編譯器
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EtV3iFye-1613061611848)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131115030599.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uVx1YGRR-1613061611849)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131184425189.png)]
為什么我們輸的是3,而列印的卻是0 ?因為我們并沒有將值真正賦給物件的age
為了避免這種無效賦值的情況,我們需要使用this
this的作用相當于告訴編譯器,你要把我傳進的引數age賦值給類物件的age,然后呼叫類物件的age列印輸出
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
}
public void printAge() {
System.out.println("My age is "+ this.age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dchxMTLs-1613061611850)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131184639113.png)]
- 本類方法
為了表示方便,在本類中呼叫本類方法,可以在呼叫的方法前加上this
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
System.out.println("My age is "+ this.age);
}
public void roar() {
System.out.println("I am yelling.");
this.Hungry();
}
public void Hungry() {
System.out.println("I am hungry!!");
}
}
這個this加或不加都沒關系,編譯器會幫我們自動加上
- 呼叫本類的其他構造方法
this可以呼叫構造方法,這樣能避免相同初始化代碼
this()是用來呼叫無參構造方法的
沒加this()
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
}
public void printAge() {
System.out.println("My age is "+ this.age);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zvACJehR-1613061611851)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131185804560.png)]
加上this();
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this(); //必須方法構造方法最前面
this.age = age;
}
public void printAge() {
System.out.println("My age is "+ this.age);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZwmzIw2j-1613061611852)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131185909356.png)]
可見,加上this()就呼叫了animal的無參構造方法
注意,this();必須在呼叫的方法最前面
this(a); 可以呼叫有參構造方法, a是有參構造需要的引數,例子如下
public class animal {
private int age;
public animal(){
this(3);
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
}
public void printAge() {
System.out.println("My age is "+ this.age);
}
}
//測驗類
public class animalTest {
public static void main(String[] args) {
animal Tom = new animal();
Tom.printAge();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-apcvmb6p-1613061611853)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131190535142.png)]
我們直接呼叫animal的無參構造,但是age是有初始值的,就是我們在無參構造中this(3);傳入的age,
方法多載Overload
方法可以多載,當然之前學習的函式也可以多載;多載后的方法可以接收不同引數
所謂的多載Overload針對同一個類,在這個類里面可以包含名字相同但是接收引數不同的的方法,例子如下,
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this();
this.age = age;
}
public void printAge() {
System.out.println("My age is "+ this.age);
}
//對printAge進行Overload
public void printAge(int year) {
this.age += year;
System.out.println("After "+year+" years. My age is "+this.age);
}
}
public class animalTest {
public static void main(String[] args) {
animal Tom = new animal(3);
Tom.printAge();
Tom.printAge(4);
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9I3kwb1h-1613061611854)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131195018061.png)]
其實方法的多載就像無參構造方法與有參構造方法一樣
物件封裝
封裝,顧名思義將資料封起來,不讓外界輕易訪問,在java開發時,我們有時不希望外界訪問或改變我們設計好的資料,此時需要將這些資料封裝起來,
為了封裝資料,我們需要一些訪問修飾符,例如public, private(這些在前面大家應該已經遇到了,但是不知道是什么)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vVjr7yf7-1613061611855)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131201852288.png)]
一般用訪問修飾符時,都用public 或 private ,public定義的資料都可以訪問,但是private的只有本類才能訪問
封裝可以使資料更安全,假如說想要獲取或改變資料,可以使用get, set, 例子如下
public int getAge() {
return age;
}
public void setAge(int age) {
//有set的好處就是,假設在給age賦值時傳入的時string型別或其他型別,set里面可以加上判斷
this.age = age;
}
物件繼承
介紹
聊完上面幾章,我們進入物件中比較重要的環節,物件繼承,這就像兒子與父親一樣,所以被繼承的類大家稱為父類,繼承的類稱之為子類
子類對于父類的繼承
- 子類繼承父類所有public方法與屬性, 也可以添加自己獨有的方法
- JAVA繼承遵循單一繼承關系, 即一個子類只能繼承一個父類
- 當子類添加自己方法時可以對父類方法進行覆寫, override, 例如父類可以使用a方法,子類繼承a方法,可以再寫一遍a方法,使a方法實作另一種
//繼承語法:
class B extends A{ } //B是子類, A是父類, 子類繼承父類
例子
package Class_Study;
//animal是父類
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
System.out.println("My age is "+ this.age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
package Class_Study;
public class TestForAnimal {
public static void main(String[] args) {
Dog kit = new Dog();
kit.roar();
}
}
class Dog extends animal{
Dog(){
System.out.println("I am a dog.");
}
//方法覆寫override
public void roar() {
//super.roar();這個super關鍵字后面再講
System.out.println("I am hungry. I need meat");
}
}
在實體化子類物件時,我們會先呼叫父類的默認構造方法,再呼叫子類的構造方法,
這就是為什么會出現"I am an animal"
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zzGaJQ6b-1613061611856)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131234622162.png)]
在上面這個例子中,dog類是animal類的子類,它繼承了父類的方法
Dog kit = new Dog(); //實體化子類物件,呼叫子類的無參構造方法
在具有繼承關系的創建中,系統先創建父類再創建子類, 如果有默認的構造方法, 先呼叫父類A的默認無參構方法,再呼叫子類B的所屬構造方法, 這就是為什么我們呼叫dog類的無參構造方法時,先列印“I am an animal.”,再列印“I am a dog.”
//方法覆寫override
public void roar() {
System.out.println("I am hungry. I need meat");
}
在子類中,子類擁有與父類相同的方法,這樣可以對父類的方法進行覆寫,(方法的Override必須是方法一樣)(即訪問修飾符+回傳值型別+名稱+傳入引數型別一樣)
多型
世間萬物都有屬于自己的類,這些類之間又可以進行分類,例如汽車,飛機等可以被分在(繼承)交通工具類里面;老師,學生,家長可以被分在(繼承)人這個類里面,我們可以用交通工具類或人類來作為汽車或學生寬泛的表示方法,
- 使用父類作為方法形參實作多型, 使方法引數型別更為寬泛
- 使用父類作為方法回傳值實作多型, 使方法可以回傳不同子類物件
例子: A a = new B(); A是B的父類
使用多型時,只能使用父類的方法或子類覆寫父類的方法, 例如
//例子
package Class_Study;
public class animal {
private int age;
public animal(){
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
System.out.println("My age is "+ this.age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
package Class_Study;
public class TestForAnimal {
public static void main(String[] args) {
animal kit = new Dog();
kit.roar(); // 作為父類的kit只能呼叫子類覆寫后的方法或自己本身的方法
}
}
class Dog extends animal{ //狗類繼承了父類animal類,覆寫了roar()這個方法
Dog(){
System.out.println("I am a dog.");
}
//方法覆寫override
public void roar() {
System.out.println("I am hungry. I need meat");
}
public void run() {
System.out.println("I can use four legs to run!!");
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-R2PomW1Q-1613061611856)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202104457940.png)]
假設我們作為父類,再呼叫子類的方法,例如這個:用kit animal類呼叫dog子類的run方法,出現錯誤
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-I5o8Lhwj-1613061611857)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202104550114.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OCuMepQD-1613061611858)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202104646229.png)]
向上轉型
格式
//Animal類是Dog類的父類
Animal a = new Dog()
剛才上面那個例子就使用了向上轉型的方法(子類轉為父類),
向下轉型
向下轉型前提是 原來實體是子類(先向上轉型):
Animal a = new Dog()
Dog dog = (Dog) a //利用強轉向下轉型
多型的好處是有很強的擴展性,例如這樣
speak(new Cat());
speak(new Dog());//此時我們將cat類與dog類作為引數傳進去
public void speak(Animal a){
a.roar(); //函式會自動向上轉型,呼叫cat與dog類中Override父類Animal的roar方法
}
instanceof關鍵字
向下轉型前,應判斷參考中物件的真實型別,以達到準確性
語法, (dog instanceof animal)//回傳結果為boolean
if (args instanceof type) {
type new_name = (type) args;
}
package Class_Study;
public class TestForAnimal {
public static void main(String[] args) {
animal animal = new Dog();
if (animal instanceof Dog) { //判斷animal的真實型別是否是Dog類,是的話進行向下轉型
Dog dog = (Dog) aanimal;
dog.run();
}
}
}
class Dog extends animal{
Dog(){
System.out.println("I am a dog.");
}
//方法重寫override
public void roar() {
System.out.println("I am hungry. I need meat");
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xQxxYVnP-1613061611859)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202115137520.png)]
super關鍵字
作為子類,我們繼承了父類的方法,但當我們繼承父類后并Override父類方法后,我們就不能再使用父類的方法,為了能再次使用,我們需要使用super關鍵字
和this()一樣,super()必須是第一條陳述句
可以呼叫父類的屬性和方法
super.upload() // 父類的方法
super.value //父類的屬性,注意這個屬性必須是public公共屬性,私有屬性無法繼承
例子,呼叫父類屬性
public class Value {
public static void main(String[] args) {
B b =new B();
b.print();
}
}
class A{
int value =10;
}
class B extends A{
int value = 20;
public void print() {
int value =30;
System.out.println(value); //就近原則,選取本方法中的value
System.out.println(this.value); //this呼叫本類中的value
System.out.println(super.value);//super呼叫父類中的value
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Rhj3h0qR-1613061611859)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202121542748.png)]
例子,呼叫父類的方法
package Class_Study;
//父類
public class animal {
private int age;
public animal(){
}
public animal(int age) {
this.age = age;
System.out.println("My age is "+ this.age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
package Class_Study;
//子類
public class TestForAnimal {
public static void main(String[] args) {
Dog dog = new Dog();
dog.roar();
}
}
class Dog extends animal{
Dog(){
System.out.println("I am a dog.");
}
//方法重寫override
public void roar() {
super.roar(); //通過super呼叫父類的roar方法
System.out.println("I am hungry. I need meat");
}
public void run() {
System.out.println("I can use four legs to run!!");
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ObOJS1cO-1613061611860)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202122338431.png)]
super也可以呼叫父類構造方法
super() // 呼叫無參構造方法
super(5, 6) //呼叫有參構造方法
在繼承章節開頭我們碰見的那個例子里面,當呼叫我們呼叫子類構造方法時,系統會自動呼叫父類的無參構造方法,即在子類無參構造之前加上super();如下
package Class_Study;
//父類
public class animal {
private int age;
public animal(){
//父類的無參構造
System.out.println("I am an animal.");
}
public animal(int age) {
this.age = age;
System.out.println("My age is "+ this.age);
}
public void roar() {
System.out.println("I am yelling.");
}
}
package Class_Study;
//子類
public class TestForAnimal {
public static void main(String[] args) {
Dog dog = new Dog();
}
}
class Dog extends animal{
Dog(){
super();
System.out.println("I am a dog.");
}
//方法重寫override
public void roar() {
super.roar();
System.out.println("I am hungry. I need meat");
}
public void run() {
System.out.println("I can use four legs to run!!");
}
}
加上super()
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0Ggqw58j-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202122732411.png)]
沒加super()
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gnFoirY4-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202122802897.png)]
編譯器默認調父類無參構造方法(在沒加super()的前提下),不管子類呼叫的是否是無參還是有參構造
當C物件繼承B物件,B物件繼承A物件時,實體化C物件,先呼叫A的無參構造,然后呼叫B的無參構造,最后呼叫C的無參構造
//子類呼叫父類的有參構造
Dog(){
super(3); //在Dog子類的無參構造方法中,呼叫父類的有參構造
System.out.println("I am a dog.");
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2ZfTYONx-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202123738106.png)]
物件是參考型別
為什么說物件是參考型別?
我們new一個物件,其實是用一個指標指向這個部分資料集合,例子如下
//創建一個Point類,有x,y值
public class Point {
private int x;
private int y;
public void SetPoint(int x, int y){
this.x =x;
this.y =y;
}
public void show() {
System.out.println("("+this.x+" , "+this.y+")");
}
}
public class TestPoint {
public static void main(String[] args) {
//實體化一個Point類
Point a = new Point();
//將a點的地址傳入SetPoint函式
SetPoint(a);
//如果物件不是參考型別,a點的x,y值就不會改變
a.show();
}
public static void SetPoint(Point b) {
b.SetPoint(5, 5);
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Ko0rP80P-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202215944627.png)]
上面例子的box diagram
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HQCsyKc1-1613061611863)(C:\Users\23881\OneDrive - Rose-Hulman Institute of Technology\未命名.jpg)]
包裝類
由于基本型別不是物件,在萬物皆物件的JAVA中,我們有時需要將這些資料封裝成物件,這就是包裝類
| 基本資料 | 包裝類 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
基本型別封裝的好處
- 方便進行物件操作
- 便于資料與字串之間的轉換
例如:將數字1轉為字串1,再將字串1轉為數字1
public class NumDemo1
{
public static void main(String[] args)
{
int i =1;
//把基本資料int封裝成Integer
Integer num = new Integer(i);
//數字轉為字串
String word = num.toString();
//列印轉成的型別
System.out.println(word.getClass());
//將字串轉為數字,列印轉成的型別
System.out.println(Integer.valueOf(word).getClass());
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ikgqHyJ3-1613061611864)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210209194231137.png)]
JAVA字串
在前面大家已經不止一次接觸到了字串String型別資料,String字串是一個功能強大的類,它可以將多個字符放在一起,如下
char word = 'h';
String words = "hello world";
字串與字符有一點區別:字串內容放在雙引號內,而字符則是單引號,
特點
- 字串是常量,創建后不可改變
- 字串字面值儲存在字串池中,可以共享
- String str = new String(“Java”)在堆里面創建一個物件
常用方法
public int length() //回傳字串長度
public char charAt(int index) //根據下標獲取字符
public boolean contains(String str) //判斷當前字串是否包含傳進去的字符str
public int indexOf(String str)//查找str首次出現的下標,存在則回傳該下標,不存在則回傳-1
public int lastIndexOf(String str)//查找字串當中最后出現的下標索引
public String trim()//去除字串前后的空格
public String toUpperCase()//全部轉為大寫
public boolean endWith(String str)//判斷字串是否是以str結尾
public boolean startWith(String str)//同樣,也有以str開頭的判斷
public String replace(char oldChar, char newChar)//將原來舊的字串替換為新的字串
public String concat(String s)//回傳連接后的字串, s是加在后面的字串
public String substring(int beginIndex, int endIndex)//回傳一個分割過后的字串
public char[] toCharArray()//將字串轉換成陣列
Arrays.toString(char[] string)//為了將陣列內的字符列印出來,呼叫Arrays工具類
下面用一串代碼來演示如何使用這些方法
package StringStudy;
import java.util.Arrays;//為了把陣列中的內容轉成字串并列印出來
public class Demo1 {
public static void main(String[] args) {
String words = "hello";
System.out.println(words);
words = "world";
System.out.println(words);
String str = new String("Java");
String str2 = new String("Java");
System.out.println("str與str2是否在同一地址:"+(str == str2));
System.out.println("str與str2是否內容完全相同"+str.equals(str2));
System.out.println("words在第一個的字串是:"+words.charAt(0));
System.out.println("將words轉化為陣列后的 Array:"+Arrays.toString(words.toCharArray()));
System.out.println("將words轉化為陣列后的Array[0]:"+words.toCharArray()[0]);
System.out.println("判斷words中是否含有w:"+words.contains("w"));
System.out.println("判斷words中是否含有wd:"+words.contains("wd"));
System.out.println("回傳對應字串rd的下標:"+words.indexOf("rd"));
words = "hello";
System.out.println("回傳對應字串l的下標:"+words.indexOf("l"));
System.out.println("回傳對應字串l最后的下標:"+words.lastIndexOf("l"));
String student = " Peter Bear ";
System.out.println("After deleting SPACE in String----"+student.trim()+"----");
System.out.println("將字母全部改為大寫:"+student.toUpperCase());
System.out.println("將原來的字串中的內容進行替換:"+student.replace("ear", "ear is 18 years old."));
String website = "www.peterbear.com";
System.out.println("回傳在原來的字串后面增添內容的字符出:"+student.concat("'s website: ").concat(website));
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SPyl6PwK-1613061611865)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202231723332.png)]
JAVA修飾符
再類物件封裝中我們提到的private, public屬于JAVA的訪問修飾符;在本章我們將介紹其他的修飾符:非訪問修飾符
static
static中文翻譯是靜態,所以關于static 的方法和屬性叫做靜態屬性和靜態方法
使用靜態修飾符后程式會發生哪些變化?
-
靜態屬性和方法利用類名進行呼叫(假如說一個類僅含有static成員,那么這個類被稱作工具類)
-
靜態成員是全類所共享的成員
-
static 關鍵字用來宣告獨立于物件的靜態變數(靜態屬性),無論一個類實體化多少物件,它的靜態變數只有一份拷貝, 靜態變數也被稱為類變數,區域變數不能被宣告為 static 變數,
//靜態屬性
static int count=10;
例子如下
package modifier;
//創建一個類,這個類有靜態屬性與非靜態屬性,含靜態方法與非靜態方法
public class StaticStudy {
public int cnt=0; //非靜態屬性
public static int cnt2=0; //靜態屬性,靜態變數
public void add() {
cnt++;
}
public static void add2() {
cnt2++;
}
public void show() {
//因為靜態成員是全類所共享的成員,所以非靜態方法可以呼叫靜態成員變數
System.out.println("非靜態計數器"+cnt);
System.out.println("靜態計數器: "+cnt2);
}
}
package modifier;
public class TestStatic {
public static void main(String[] args) {
StaticStudy num = new StaticStudy();//實體化一個類物件
num.show();//初始值,呼叫show非靜態方法
num.add();
StaticStudy.add2();//通過類名呼叫靜態方法
num.show();//add后的值
System.out.println("類名呼叫靜態屬性: "+StaticStudy.cnt2);//類名呼叫靜態屬性
System.out.println("----實體化第二個物件"+"----");
StaticStudy num2 = new StaticStudy();//再實體化一個類物件
num2.add();
StaticStudy.add2();
num2.show();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3pDt1S75-1613061611866)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203133932014.png)]
從上面例子我們不難發現無論一個類實體化多少物件,它的靜態變數只有一份拷貝,
靜態方法
特點
- 靜態方法可以直接訪問靜態成員
private static int cnt3=0;
public static int cnt2=0; //靜態屬性,靜態變數
public static void add2() { //靜態方法給cnt2加一
cnt2++;
}
- 但是靜態方法不能直接訪問非靜態成員
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sc5hPlgF-1613061611867)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203125411520.png)]
- 靜態方法不能使用this和super關鍵字
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ARoVq8mg-1613061611867)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203134731231.png)]
- 靜態方法不能重寫,只能繼承,沒有多型
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-PGG1TWGV-1613061611868)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203135945647.png)]
靜態代碼塊
static{ }
//整個程式執行程序中,只執行一次
//可以執行一些必要的初始化行為
//與其相反的是非靜態代碼塊
{
}
靜態代碼塊中只能放靜態成員
系統初始化程序:靜態代碼塊---->main函式---->非靜態代碼塊---->建構式
這里請參考下面的鏈接
靜態類
倘若一個類是靜態的,它一定是靜態內部類//這個在講到內部類的時候再具體分析
final
final意為最終的,最后的,即不可變的
最終類
final修飾的不能被繼承, 例如String, Math,System類,這些類的均無法被繼承
當FinalStudy準備繼承Point類時,由于Point類是被final修飾,所以無法被繼承
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-op8xRSgo-1613061611868)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203144245874.png)]
最終變數
final int num = 10;
final static string address = "school";
只能被賦值一次(常量)
1. 在構造方法中賦值
如果有一個對常量賦值,其他的構造方法都要對其進行賦值
2. 創建常量時直接賦值
我們創建了一個Point類,使用final修飾了原點,當我們想要改變原點資料時,失敗
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jvHcb2d3-1613061611870)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203145808713.png)]
對于最終變數有兩種初始化方法,
第一種:直接創建時就賦值
final int Origion_x=0;
final int Origion_y=0;
第二種:使用代碼塊進行賦值
final int Origion_x;
final int Origion_y;
{
Origion_x=0;
Origion_y=0;
}
第三種:在構造方法中
final int Origion_x;
final int Origion_y;
Point(){
Origion_x=0;
Origion_y=0;
}
倘若變數用static + final修飾,為靜態常量,初始化要在靜態代碼塊中進行
第一種:直接創建時就賦值
static final int Origion_x=0;
static final int Origion_y=0;
第二種:使用代碼塊進行賦值
static final int Origion_x;
static final int Origion_y;
static{
Origion_x=0;
Origion_y=0;
}
最終方法
不能被子類覆寫或者重寫,只能繼承
我們給父類的Print方法加上final修飾后,子類FinalStudy無法Override Print方法,所以只能繼承該方法
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zfanjxGD-1613061611870)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203144655295.png)]
例子如下
package modifier;
public class FinalStudy extends Point{
}
class Point{
private int x;
private int y;
public void SetPoint(int x, int y) {
this.x =x;
this.y =y;
}
public final void Print() {
System.out.println("( "+this.x+", "+this.y+" )");
}
}
package modifier;
//測驗
public class TestFinal {
public static void main(String[] args) {
FinalStudy point = new FinalStudy();
point.SetPoint(1, 2);
point.Print();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Jlc1QG5v-1613061611871)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203145143119.png)]
物件常量
final修飾基本型別:值不可變
final 修飾參考型別:地址不可改變
例子如下
class Point{
private int x;
private int y;
static final int Origion_x;
static final int Origion_y;
static{
Origion_x=0;
Origion_y=0;
}
public void SetPoint(int x, int y) {
this.x =x;
this.y =y;
}
public void Print() {
System.out.println("原點: "+"( "+Origion_x+", "+Origion_y+" )");
System.out.println("( "+this.x+", "+this.y+" )");
}
}
package modifier;
import java.util.Arrays;
public class TestFinal {
public static void main(String[] args) {
final int[] nums = new int[] {1,3,5,7};
System.out.println(Arrays.toString(nums));
// nums = new int[] {5,6,7};//此時不能對nums再進行賦值,因為已經nums已經變成了常量
nums[0] = 9; //但是nums內部的資料可以進行更改,因為nums是參考型別
System.out.println(Arrays.toString(nums));
final Point p1 = new Point();
p1.SetPoint(6, 6);
p1.Print();
p1.SetPoint(10, 10);
p1.Print();
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vMvOHovl-1613061611871)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203154357345.png)]
abstract
abstract中文意思是抽象,抽象即為不具體
抽象類
一個類不能同時被abstract和final修飾
當類物件沒有具體的含義,可以將該類改為抽象類
例如Animal類,它本身沒有任何意義各種方法比較抽象,但是繼承Animal類的子類Dog類和Cat類有意義,所以要把Animal類改為抽象類
作用:
- 可以被子類繼承,提供共性的屬性和方法
- 可以宣告為參考,更自然的使用多型
抽象類當中可以包含抽象方法,也可以包含非抽象方法
//語法:
public abstract class Animal{ }
如果一個類被改為抽象類,該類就不可以被實體化, 即不能new 物件;但是我們能夠用這個類來作為參考,就像多型向上轉型一樣
下面是一個關于抽象類的例子
package modifier;
public class TestAbstract {
public static void main(String[] args) {
Dog dog = new Dog();
dog.speak();
Animal bird = new Bird(); //可以宣告為參考,更自然的使用多型
bird.speak();
//dog和bird呼叫父類的walk方法
dog.walk();
bird.walk();
}
}
abstract class Animal{
public abstract void speak();
public abstract void move();
//抽象類中包含非抽象方法
public void walk() {
System.out.println("I am walking");
}
}
class Dog extends Animal{
@Override
public void speak() {
System.out.println("Wang Wang Wang……");
}
@Override
public void move() {
System.out.println("Dog uses his four legs to run");
}
}
class Bird extends Animal{
@Override
public void speak() {
System.out.println("Yin Yin Yin……");
}
@Override
public void move() {
// TODO Auto-generated method stub
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5xEga0Yh-1613061611872)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203162947766.png)]
抽象方法
一但類當中包含抽象方法,此類必須是抽象類
父類物件的方法本身沒有意義,但為了實作多型(向上轉型)又不得不保留
Animal dog = new Dog();
dog.eat();
抽象方法只有方法的宣告,沒有方法實作,此外抽象方法只能在抽象類當中
//格式
public abstract void eat();
子類繼承父類,子類必須重寫父類的抽象方法,否則子類必須是抽象類
//抽象的felid貓科動物類繼承抽象的動物類,其中增添了抽象的貓科動物捕獵方法
abstract class felid extends Animal{
abstract void hunt();
}
抽象類與抽象方法的小案例:
建立一個Vehicle的交通工具抽象類和一個主人類,列印主人回家時開的什么車,是什么品牌
package Polymophic_And_Abstract;
public class Master {
private final String name; //將主人的名字封裝起來
public Master(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void GoHome(Vehicle vehicle) {
System.out.println(this.getName()+"回家了");
vehicle.run();
}
}
package Polymophic_And_Abstract;
public class TestForVehicle {
public static void main(String[] args) {
Master jim = new Master("Jim");
Vehicle car = new Car("奔馳");
jim.GoHome(car);
}
}
//創建一個抽象的Vehicle類
abstract class Vehicle {
private final String band;
public Vehicle(String band) {
this.band = band;
}
public String getBand() {
return band;
}
//一個抽象方法
public abstract void run();
}
//Car繼承抽象的Vehicle交通工具類
class Car extends Vehicle{
public Car(String band) {
super(band);
}
//implements 實作run()方法
@Override
public void run() {
System.out.println(super.getBand()+"牌的車在路上跑");
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LD8zFs2k-1613061611872)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203170116415.png)]
JAVA介面
介紹
介面相當于是特殊的抽象類,定義方法,組成部分與抽象類類似
介面沒有構造方法,所以不能創建物件但是可以implements,一個類可以實作多個介面,例如
C extends A implements B implements C
介面也可以和父類一樣實作多型(向上轉型)
僅可呼叫介面中實作的方法,不能呼叫實體化物件所獨有的方法
介面往往可以代表一種能力,一但類物件實作了該介面,它也具備了這種能力
實作介面時,訪問修飾符必須是public
介面與抽象類相同之處:
- 可編譯成位元組碼檔案
- 不能創建物件
- 可以作為參考型別 // 當作為參考型別時,僅可呼叫實作了的介面;
- 具有Object類中定義的方法(Object類是所有類物件的父類)
不同之處:
- 介面所有屬性都是用public static final修飾
- 介面所有方法都是用public abstract 修飾
- 介面沒有構造方法,動態代碼塊和靜態代碼塊
類無法使用多繼承,但是介面可以實作多繼承介面
package Interface;
public interface Ability extends flyable, swimmable{
public abstract void fire();
}
interface flyable{
public abstract void fly();
}
interface swimmable{
public abstract void swim();
}
interface關鍵字
類物件是class,而介面則是interface
public interface A{
public static final String FIELD = "Value"
public abstract void method();
}
注意
介面只能定義:公開靜態常量 和***公開抽象方法***
public static final String FIELD="Value"; //公開靜態常量,使用時,直接用介面進行呼叫
public abstract void method();//公開抽象方法只用寫回傳值型別和方法名
類一但implement就必須實作覆寫介面中全部抽象方法,此類就是該介面的實作類
補充
標記介面,例如Serializable介面
public interface Serializable{}; //表示實作這個介面的物件可以被序列化和克隆
public interface Cloneable{};
案例
- 給人實作飛的能力
//先創建fly的介面
package Interface;
public interface fly {
public abstract void fly();
}
//然后創建一個人類,來實作fly介面
package Interface;
public class Person implements fly{
String name;
int age;
Person(String name, int age){
this.name= name;
this.age = age;
}
public void eat() {
System.out.println(this.name+" 在吃飯……");
}
public void sleep() {
System.out.println(this.name+" 在睡覺……");
}
//由于繼承了介面,我們必須實作介面的方法
@Override
public void fly() {
System.out.println(this.name+" can fly");
}
}
//寫一個測驗類
package Interface;
public class TestPerson {
public static void main(String[] args) {
Person jim = new Person("Jim",20);
jim.fly();
//利用介面作為參考型別
fly baby = new Person("baby", 30);
baby.fly();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BKnAsRfa-1613061611874)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203194232960.png)]
- USB案例
USB介面是大家熟知的一種介面,風扇,U盤,都是USB介面,我們要將USB介面插入電腦
//1先創建USB介面
package USB_Interface;
public interface USB {
public abstract void Service();
}
//2實作Fan,U盤的介面
//U盤
public class USB_Flash implements USB {
@Override
public void Service() {
System.out.println("USB-Flash has connected to the computer");
}
}
//風扇
public class Fan implements USB{
@Override
public void Service() {
System.out.println("Fan starts to run");
}
}
//3由于我們要將U盤和風扇插入電腦中,所以要創建一個電腦類
package USB_Interface;
public class Computer {
private USB usb1;
private USB usb2;
public USB getUsb1() {
return usb1;
}
public void setUsb1(USB usb1) {
this.usb1 = usb1;
}
public USB getUsb2() {
return usb2;
}
public void setUsb2(USB usb2) {
this.usb2 = usb2;
}
public void Run() {
System.out.println("Computer starts to work!!");
if(this.getUsb1() != null) {
usb1.Service();
}
if(this.getUsb2() != null) {
usb2.Service();
}
}
}
//4最終的測驗類
package USB_Interface;
public class Test_USB {
public static void main(String[] args) {
Computer Windows = new Computer();
Windows.setUsb1(new Fan());
Windows.setUsb2(new USB_Flash());
Windows.Run();
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3MSfafuL-1613061611874)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203200029587.png)]
JAVA內部類
創建在類內部的類叫做內部類,
class Outer{
//外部類
class Inner{
//內部類
}
}
內部類擁有和普通類一樣的屬性,可以擁有方法,能夠去實作介面,繼承
如果外部類與內部類成員屬性名字相同,則優先訪問內部類成員
如果想要訪問同名外部類成員,需要先寫上外部類名字,再this.name,或直接Outer.this.name
既然已經有了外部類,那為什么還要內部類呢?
好處
- 內部類可以對外部類全部內容進行訪問
- 方便訪問外部類的私有屬性(內部類可直接訪問外部類的私有成員而不破壞封裝)
成員內部類
package InnerClass;
import InnerClass.OuterClass.InnerClass;
public class NormalInnerTest {
public static void main(String[] args) {
//1. 第一種實體化內部類的方法
//OuterClass outer = new OuterClass();
//InnerClass inner = outer.new InnerClass();
//2. 第二種實體化內部類的方法,一步到位
InnerClass inner = new OuterClass().new InnerClass();
inner.print();
}
}
class OuterClass{
private String words="Outer Class";
class InnerClass{
public void print() {
System.out.println(OuterClass.this.words);
new OuterClass().print();
System.out.println("Inner Class: Hello World");
}
}
public void print() {
System.out.println(words+": Hello World");
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hkMTS7sx-1613061611875)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210204213254151.png)]
成員內部類不能定義靜態成員
靜態內部類
靜態內部類可以不依賴外部類物件實體化物件
只有靜態內部類可以用static修飾
//實體化靜態內部類
Outer.Inner StaticInnerDemo =new Outer.Inner();
案例
package InnerClass;
class Outer{
//外部類中包含靜態成員變數與非靜態成員變數
private static String inf = "Hello World";
private String inf2 = "GoodBye World";
//創建靜態內部類
public static class Inner{
//靜態內部類里面包含靜態方法與非靜態方法
private static void print() {
System.out.println("\t靜態成員變數: "+inf);
//靜態內部類無法直接呼叫非靜態變數
// System.out.println(inf2);
//由于外部類成員變數為私有,需要借助外部類來訪問
Outer out = new Outer();
System.out.println("\t非靜態成員變數: "+out.inf2);
}
//非靜態方法
public void print2() {
System.out.println("\t非靜態方法呼叫靜態成員變數: "+inf);
}
}
//普通內部類
public class Inner2{
//普通成員內部類無法創建靜態方法
public void print() {
//但是可以呼叫外部類中的靜態成員變數
System.out.println("\t靜態成員變數: "+inf);
System.out.println("\t非靜態成員變數: "+inf2);
}
}
//外部類能夠創建非靜態方法
public void fun() {
//在外部類的方法中實體化內部類
Inner innerDemo = new Inner();
System.out.println("靜態內部類的靜態方法");
//直接通過內部類類名訪問靜態方法
Inner.print();
System.out.println("靜態內部類的非靜態方法");
//訪問內部類非靜態方法需要通過實體化的物件來訪問
innerDemo.print2();
}
}
public class InnerClassDemo1 {
public static void main(String[] args) {
//實體化靜態內部類
Outer.Inner StaticInnerDemo =new Outer.Inner();
//實體化普通內部類
Outer shell = new Outer();
shell.print();
Outer.Inner2 NormalInnerDemo = shell.new Inner2();
System.out.println("靜態內部類的非靜態方法");
StaticInnerDemo.print2();
System.out.println("普通內部類的方法");
NormalInnerDemo.print();
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-470Blw7C-1613061611875)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210204215906597.png)]
區域內部類
把一個類定義在方法內部,這個類叫做區域內部類,就像定義在方法中的變數叫區域變數一樣
區域內部類不能定義訪問修飾符,即不能定義為static
但是可以包含靜態常量,private final static int count =2000;
public void fun(final String temp){
class Inner{
public void print(){
System.out.println(info);
System.out.println(temp);
}
}
//實體化內部類,呼叫內部類方法
new Inner().print();
}
匿名內部類
在java中處理內部類之外,還有一種匿名內部類,
匿名內部類就是指沒有一個具體名稱的類,此概念是在介面和抽象類的應用上發展起來的,
有時這種類只用一次,命名又可惜,所以就使用匿名內部類
以之前寫的Ability介面為例
//介面
package InnerClass;
public interface Ability extends flyable{
public abstract void swim();
}
interface flyable{
public abstract void fly();
}
package InnerClass;
import Interface.Ability;
public class AnonymousInnerClass {
public static void main(String[] args) {
Ability SuperMan = new Ability(){
@Override
public void swim() {
// TODO Auto-generated method stub
System.out.println("I can swim");
}
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can fly");
}
};
SuperMan.swim();
SuperMan.fly();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fPyxVxD5-1613061611875)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210204225913164.png)]
使用匿名內部類時,必須繼承一個父類或實作一個介面
JAVA泛型
JAVA泛型英文generics,
本質是引數化型別,就是把型別作為引數傳遞,泛型物件不能被實體化:T type = new T();
這么說大家估計還是覺得這個定義比較抽象,
舉個例子:我們要寫一個排序方法,這個方法能夠對int型別,String型別,double型別都進行排序,此時要使用泛型方法
泛型可以提高代碼的重復性,防止型別轉換例外,提高代碼的安全性
泛型字母含義
E - Element:指集合中的元素
T - Type:Java型別,種類
K - Key:鍵
V - Value:值
N - Number:數值型別
格式
<T,...> //T是型別占位符,是一種參考型別
泛型方法
泛型方法可以接收不同型別的引數,根據傳進去的引數做適當的處理,格式如下
//<T> 宣告此方法為泛型方法, T指出回傳值是泛型T
//Class<T> 指明泛型T的具體型別, c用來創建泛型T代表的類物件
public <T> T getObject(Class<T> c){
//創建一個泛型物件
T t = c.newInstance();
return t;
}
例子,有三個不同型別的陣列,分別列印出其中的值
package GenericsStudy;
public class GenericDemo1 {
//泛型方法
public static < E > void printArray(E [] inputArray) {
//輸出陣列元素
for (E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String[] args) {
//創建不同型別陣列
Integer[] intArray = {1, 2, 3, 4, 5};
Double[] doubleArray = {1.1, 2.2, 3.3, 4.4};
Character[] charArray = {'H', 'E', 'L','L','O'};
System.out.println("整型陣列元素為:");
//因為是寫在本類里面,所以可以直接呼叫
//如果是測驗類寫在本類外面,需要通過類名來呼叫靜態方法,
printArray(intArray);
System.out.println("\n雙精度型陣列元素:");
printArray(doubleArray);
System.out.println("\n字串陣列元素:");
printArray(charArray);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bNTFMXgx-1613061611876)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205114935980.png)]
案例2
撰寫一個add方法,傳入不同型別的數字型別,并回傳相加的值,相加的值是double型別
package GenericsStudy;
public class GenericsDemo5 {
//extends是為了做泛型界定,即泛型T必須是Number的子類
public static <T extends Number> double add(T num1, T num2) {
double sum=0.0;
sum = num1.doubleValue() + num2.doubleValue();
return sum;
}
public static void main(String[] args) {
System.out.println("double 型別相加:5.5 + 6.7 ="+add(5.5, 6.7));
System.out.println("int 型別相加:5 + 7 ="+add(5, 7));
System.out.println("double 與 int 型別相加:5.5+6 ="+add(5.5, 6));
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-h5bQ1WUk-1613061611876)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205211611985.png)]
泛型類
既然方法可以定義為泛型,類也可以定義成泛型
泛型類中可以包含泛型方法,多個型別引數
package GenericsStudy;
public class GenericDemo3<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return this.t;
}
public static void main(String[] args) {
GenericDemo3<Integer> one = new GenericDemo3<Integer>();
GenericDemo3<String> two = new GenericDemo3<String>();
one.add(1);
two.add("Hello World");
System.out.println(one.get());
System.out.println(two.get());
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-I2ZSAv5l-1613061611877)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205214226660.png)]
上面提到了,泛型可以存盤多個型別,下面我們來寫一個簡易字典,僅包含一對key和value
package GenericsStudy;
public class GenericDemo6 {
public static void main(String[] args) {
Dictionary<String, Integer> dic1 = new Dictionary<String, Integer>();
dic1.put("Peter",110);
System.out.println(dic1.getKey());
System.out.println(dic1.getValue());
System.out.println(dic1.getAll());
}
}
class Dictionary<K, V>{
private K key;
private V value;
public void put(K key, V value) {
this.key = key;
this.value = value;
}
//獲取key
public K getKey() {
return key;
}
//獲取value
public V getValue() {
return value;
}
//獲取key與value的字串
public String getAll() {
return key.toString()+":"+value.toString();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fJEknvNO-1613061611878)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205215953250.png)]
泛型介面
繼承了泛型介面的類會變成泛型類
package GenericsStudy;
public class GenericDemo7 {
public static void main(String[] args) {
ImpleData<String> Imple = new ImpleData<String>();
Imple.print("Hello World");
}
}
//創建一個泛型介面
interface Data<T>{
T getData(T t1);
}
//ImpleData實作了Data介面
class ImpleData<T> implements Data<T>{
@Override
public T getData(T t1) {
return t1;
}
public void print(T t1) {
System.out.println("Print: "+this.getData(t1));
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-S8qvVnlv-1613061611879)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205221855579.png)]
通配符
通配符是指這個 問號:?,
List <?> seq = new ArrayList<>();
- <? extends T>表示該通配符所代表的型別是T型別的子類,
? extends通常與List一起用,List是一種存盤資料的容器和Array陣列類似,在后面的章節有介紹
package GenericsStudy;
import java.util.List;
public class GenericDemo4 {
public static void main(String[] args) {
/*由于我們extends Number了,種類只能是Number類或Number的子類
如果使用String型別,會報錯 */
List<Number> sequence = new ArrayList<>();
sequence.add(1);
sequence.add(2);
sequence.add(1.4);
sequence.add(7.9f);
getDate(sequence);
}
public static void getDate(List<? extends Number> data) {
for(Object i : data) {
System.out.println(i);
}
}
}
- <? super T>表示該通配符所代表的型別是T型別的父類,
-
不能同時宣告泛型通配符上界和下界
JAVA集合
我們Java后端一般要進行資料處理,假設所有資料都是儲存在陣列里面,大小長度受限,不方便;所以我們在本章將引進集合的概念,集合是物件的容器,定義了對多個物件進行操作的常用方法,可實作陣列的功能,但比陣列更靈活,注意:陣列可以存盤基本型別,如int,但是集合只能存盤參考型別,如String,所以在集合中存數字時,要將int型別轉化為Integer型別
對于集合中的元素我們想要遍歷有2種方法
- 增強for(for each回圈)
for(Object i :container1) {
System.out.println(i);
}
- 通過迭代器來遍歷
//迭代器是通過集合內部的方法來獲得的
Iterator<Object> itr = container1.iterator();
//itr.hasNext()是判斷是否還有下一個元素,如果是,該回圈開始執行
while(itr.hasNext()) {
//列印出下一個元素
System.out.println(itr.next());
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5kVeBFEv-1613061611880)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210207164038116.png)]
Collection介面
Collection介面是眾多集合的父介面,List介面,Set介面都是繼承Collection介面,然后通過實作類實作其中的方法,由于Collection,Set, List都是介面,創建時必須要用實作類;比如List的實作類ArrayList,Set的實作類HashSet.
//引入集合模塊
import java.util.Collection
//創建集合,由于Collection是介面,我們用Collection的實作類ArrayList來實作
//Collection集合是泛型集合,< >中我們要添加存盤的資料型別, Object類是所有類的父類
Collection<Object> container1 = new ArrayList<>();
由于集合是無法儲存基本型別的,當我們存入基本型別時,集合會自動裝箱
list.add(20); 實際上是list.add(new Integer(20));
如果有一些方法解釋不全,可以參考以下API鏈接
API: https://www.runoob.com/manual/jdk1.6/
| 常用方法 | 作用 | 例子 |
|---|---|---|
| boolean add(E e) | 添加元素,添加成功回傳true | container1.add(“apple”); |
| void clear() | 移除collection中的所有元素 | container1.clear(); |
| int size() | 回傳集合中元素的個數 | int size = container1.size(); |
| boolean contains(Object o) | 如果此 collection 包含指定的元素,則回傳 true | container1.contains(“apple”); |
| Iterator iterator() | 回傳collection的所有元素的迭代器 | Iterator itr = container1.iterator(); |
| boolean isEmpty() | 判斷此集合是否為空 | container1.isEmpty(); |
| boolean remove(Object o) | 移除集合中的某物件 | container1.remove(1); |
| Object[] toArray | 將此集合轉為陣列 | Object[ ] arrray = container1.toArray(); |
例子1
package CollectionStudy;
import java.util.ArrayList;//引入ArrayList
import java.util.Collection;//引入Collection
import java.util.Iterator; //引入迭代器
public class CollectionDemo1 {
public static void main(String[] args) {
//使用多型
Collection<Object> container1 = new ArrayList<>();
//添加元素
container1.add("apple");
container1.add(1);
//增強for遍歷元素
System.out.println("----增強For----");
for(Object i :container1) {
System.out.println(i);
}
//迭代器遍歷元素
System.out.println("----Iterator----");
Iterator<Object> itr = container1.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0fxJJdV0-1613061611880)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210207115019530.png)]
例子2
Collection集合可以存盤其他參考資料型別,我們創建一個學生類,并將學生類添加進ArrayList集合(Collection的實作類)
package CollectionStudy;
//Students類
public class Students {
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
//重寫toString方法,按照我們的規定回傳字串
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
}
//測驗類
package CollectionStudy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo2 {
public static void main(String[] args) {
Students Tom = new Students(18, "Tom");
Students Jimmy = new Students(22, "Jimmy"); //先實體化2個students物件
Collection<Students> container = new ArrayList<Students>();
container.add(Tom);
container.add(Jimmy);
//遍歷 1
for(Object student : container) {
System.out.println(student);
}
System.out.println("\t----Line-----");
//遍歷 2
Iterator<Students> itr = container.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5vVj96uo-1613061611881)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210207165739022.png)]
我們想用集合的contains方法,來判斷是否包含某參考元素
Students Jimmy = new Students(22, "Jimmy");
Collection<Students> container = new ArrayList<Students>();
container.add(Jimmy);
System.out.println(container.contains(Jimmy));
結果是:true
假設我們傳進去的不是Jimmy,而是: new Students(22, “Jimmy”)
結果是:false
為了避免這個問題,我們需要重寫students類中的equals方法
//在Students類中重寫此方法
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj == null) {
return false;
}
if(obj instanceof Students) {
Students students = (Students) obj;
if(this.name.equals(students.name)&&this.age == students.age) {
return true;
}
}
return false;
}
再次呼叫測驗類
結果為:true
List介面
List是有序(添加順序與遍歷順序一致),有下標,元素可重復的集合
List的獨有方法
如果有一些方法解釋不全,可以參考以下API鏈接
API: https://www.runoob.com/manual/jdk1.6/
| 方法 | 解釋 | 例子 |
|---|---|---|
| void add(int index, Object o) | 在index位置插入物件o | conatiner2.add(0, “Hello”); |
| boolean addAll(int index, Collection c) | 將一個集合元素增添到index位置 | container2.addAll(0,container1); |
| Object get(int index) | 回傳集合中指定位置的元素 | container2.get(0); |
| List subList(int fromIndex, int toIndex) | 回傳fromIndex與toIndex之間的元素 | container2.subList(0, 5); |
ArrayList
ArrayList是由陣列結構實作的,查詢快,增刪慢
增添包:import java.util.ArrayList;
構造方法:ArrayList container = new ArrayList<>();
E為泛型即ArrayList可以增添任何類
| 常用方法 | 解釋 |
|---|---|
| public boolean add(E e); | 添加元素 |
| public E get(int index) | 按照索引獲取元素,從0開始 |
| public E set(int index, E element) | 可以替換指定元素 |
| public boolean remove(Object 0) | 根據內容洗掉元素 |
| public E remove(int index) | 根據index洗掉元素,回傳洗掉元素 |
例子
我們要創建一個Students類,將幾個students物件存入ArrayList類中
package CollectionStudy;
public class Students {
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
}
package CollectionStudy;
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayListCollection {
public static void main(String[] args) {
ArrayList<Students> container = new ArrayList<>();
Students Jim = new Students(18, "Jim");
Students Tom = new Students(20, "Tom");
//成功add元素后,回傳是否成功
System.out.println("是否增添了Jim:"+container.add(Jim));
container.add(Tom);
System.out.println("獲取第一個元素:"+container.get(0));
//把第2個元素設定為Alex
container.set(1, new Students(78, "Alex"));
System.out.println("第2個元素是:"+container.get(1));
//container包含的元素個數
System.out.println("元素個數:"+container.size());
//將ArrayList轉化為陣列
Object[] array = container.toArray();
System.out.println("將ArrayList轉化為陣列:"+Arrays.toString(array));
//洗掉元素,洗掉Jim的資訊
System.out.println("洗掉: "+container.remove(Jim));
System.out.println("洗掉后個數:"+container.size());
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-f4FSI5pI-1613061611882)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208192224042.png)]
假如我們增添,洗掉時用的不是Jim, 而是new Students(18, “Jim”); ?
package CollectionStudy;
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayListCollection {
public static void main(String[] args) {
ArrayList<Students> container = new ArrayList<>();
Students Jim = new Students(18, "Jim");
// Students Tom = new Students(20, "Tom");
System.out.println("是否增添了Jim:"+container.add(Jim));
container.add(new Students(20, "Tom"));
System.out.println("獲取第一個元素:"+container.get(0));
//把第2個元素設定為Alex
container.set(1, new Students(78, "Alex"));
System.out.println("第2個元素是:"+container.get(1));
//container包含的元素個數
System.out.println("元素個數:"+container.size());
//將ArrayList轉化為陣列
Object[] array = container.toArray();
System.out.println("將ArrayList轉化為陣列:"+Arrays.toString(array));
//洗掉元素,注意,此時我們new Students(18,"Jim");
System.out.println("洗掉: "+container.remove(new Students(18, "Jim")));
System.out.println("洗掉后個數:"+container.size());
}
}
結果
即使我們洗掉new Students(18,“Jim”);(內容相同),但是還是無法完全洗掉,洗掉回傳為false
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Aiks5UEV-1613061611882)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208192723418.png)]
所以此時我們需要重寫Students里面的equals方法(ArrayList判斷remove時呼叫的方法)
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj == null) {
return false;
}
if(obj instanceof Students) {
Students students = (Students) obj;
if(this.name.equals(students.name)&&this.age == students.age) {
return true;
}
}
return false;
}
結果,成功洗掉
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CODsJJaJ-1613061611883)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208193019582.png)]
LinkedList
Link意思為鏈,鏈表集合就像所以資料被鏈子連接在一起一樣
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-T7g0GKYZ-1613061611884)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208193746827.png)]
特點:鏈表結構實作,增刪快,查詢慢
使用方法與ArrayList類似
例子
繼續用LinkedList存盤Students類的資訊
同樣,我們先不重寫equals方法
package CollectionStudy;
public class Students {
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
}
package CollectionStudy;
import java.util.LinkedList;
public class LinkedListDemo1 {
public static void main(String[] args) {
LinkedList<Students> container = new LinkedList<>();
System.out.println("增添Tom: "+container.add(new Students(20, "Tom")));
container.add(new Students(18, "Jim"));
//pop從container中彈出元素
System.out.println("Pop第一個元素:"+container.pop());
container.add(new Students(18, "Jim"));
container.add(new Students(72,"Trump"));
System.out.println("洗掉元素Jim:"+container.remove(new Students(18, "Jim")));
//遍歷
for(Object i :container) {
System.out.println(i);
}
}
}
結果Jim無法被洗掉,同時***我們還發現List可以存盤相同的元素***
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vsjNqaj3-1613061611885)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208200323333.png)]
此時,我們再重寫Students的equals方法
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj == null) {
return false;
}
if(obj instanceof Students) {
Students students = (Students) obj;
if(this.name.equals(students.name)&&this.age == students.age) {
return true;
}
}
return false;
}
結果,成功洗掉
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dNaB7hId-1613061611885)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208200612292.png)]
Set介面
上文我們介紹了List介面與其的實作類,現在我們開始講Set介面
Set是無序(添加順序與遍歷順序不一致),無下標,***元素不可重復***的集合
但是使用new可以插入內容相同的元素,因為Set判斷的依據是equals方法,如果equals方法未重寫則根據地址判斷.
例子引入
package setStudy;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetIntroduction {
public static void main(String[] args) {
//我們使用Set集合的實作類HashSet來創建集合
Set<Object> container = new HashSet<>();
container.add("Hello");
container.add("World");
container.add("Hello");
container.add("My Friend");
Iterator<Object> itr = container.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
這里由于是字串,系統內部有equals方法,所以第二個"Hello"無法加入Set集合
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rxbghmdD-1613061611886)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208202251947.png)]
HashSet
HashSet是Set集合的一個實作類
存盤結構:哈希表(陣列+鏈表+紅黑樹)
存盤程序
(1)根據hashcode計算保存的位置,如果此位置為空,則直接保存,如果不為空,則執行第二步
(2) 再執行equals方法,如果equals方法為true,則認為重復,否則形成鏈表,即添加到HashSet容器中
因為HashSet是以equal與hashcode進行比較,所以要重寫hashcode與equals,這樣就可以排除new的干擾,
構造方法
//E為任意種類的資料
HashSet<E> container = new HashSet<>();
基本操作與List / Set / Collection類似
增添元素:add(E e);
洗掉元素:remove(E e);
也有迭代器:Iterator iterator();
package setStudy;
import java.util.HashSet;
public class HashSetStudy {
public static void main(String[] args) {
HashSet<String> container = new HashSet<>();
container.add("tim");
container.add("Ketty");
container.add("Yellow");
System.out.println("HashSet中的內容:"+container.toString());
System.out.println("HashSet的大小:"+container.size());
System.out.println("此HashSet中是否含有Ketty資料:"+container.contains("Ketty"));
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YvBItWvM-1613061611887)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208203127750.png)]
案例2
像ArrayList一樣,我們創建Students類,增添Students元素
package setStudy;
public class Students {
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
}
package setStudy;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetDemo2 {
public static void main(String[] args) {
HashSet<Object> container = new HashSet<>();
System.out.println("添加成功:"+container.add(new Students(18, "Jim")));
System.out.println("添加成功:"+container.add(new Students(19, "Jone")));
System.out.println("添加成功:"+container.add(new Students(18, "Alex")));
System.out.println("添加成功:"+container.add(new Students(18, "Jim")));
Iterator<Object> itr = container.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-INqkJjIu-1613061611888)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208204141673.png)]
當我們增添內容相同的元素new Students(18, “Jim”)時,系統先判斷是否是同一地址,如果沒有看是否重寫了equals和hashcode方法,因為判斷地址不一樣又沒重寫equals方法(照系統默認的equals方法),所以添加成功
現在我們重寫Students類的equals和hashcode方法
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj == null) {
return false;
}
if(obj instanceof Students) {
Students students = (Students) obj;
if(this.name.equals(students.name)&&this.age == students.age) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
//第一種轉換string的方法
// String age = String.valueOf(this.age);
//第二種
// String age = this.age+"";
String age = Integer.toString(this.age);
return age.hashCode()*this.name.hashCode();
}
結果,相同內容的資料添加失敗
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GX7opgtZ-1613061611888)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208204223172.png)]
TreeSet
實作Set介面的還有一個類,TreeSet,基于排列順序實作元素不重復
此實作為基本操作(add、remove 和 contains)
實作了SortedSet介面,對集合元素自動排序
傳入TreeSet的元素物件型別必須實作Comparable介面(指定排序規則)
因為TreeSet是通過ComparaTo方法確認是否為重復元素,所以可以通過內部類來override比較方法
使用TreeSet時,最好不要用Object類
package setStudy;
import java.util.TreeSet;
public class TreeSetStudy {
public static void main(String[] args) {
TreeSet<String> container = new TreeSet<>();
container.add("Hello");
container.add("xyz");
container.add("world");
container.add("hello");
container.add("99");
System.out.println(container.toString());
}
}
String型別,(0,1,2…)默認數字在前–>大寫–>小寫(a,b,c…z)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qX8419Ic-1613061611889)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208204509037.png)]
案例2
還是Students的案例
package setStudy;
public class Students {
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
}
package setStudy;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetStudy {
public static void main(String[] args) {
TreeSet<Students> container = new TreeSet<>();
System.out.println("添加成功:"+container.add(new Students(18, "Jim")));
System.out.println("添加成功:"+container.add(new Students(19, "Jone")));
System.out.println("添加成功:"+container.add(new Students(18, "Alex")));
System.out.println("添加成功:"+container.add(new Students(18, "Jim")));
//遍歷
Iterator<Students> itr = container.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
由于我們再Students類中沒有重寫CompareTo方法,報錯
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-NIbDItbe-1613061611890)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208205925362.png)]
繼承Comparable介面重寫CompareTo方法
package setStudy;
public class Students implements Comparable<Object>{
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
@Override
public int compareTo(Object obj) {
Students stu = (Students) obj;
return (stu.name.hashCode() - this.name.hashCode());
}
}
此時TreeSet根據我們重寫的compareTo方法來判斷Object是否重復,我們的判斷依據是students的名字的hashcode,
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9iik1hVF-1613061611890)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208211200435.png)]
Map介面
Map是一種將Key與value(鍵物件與值物件)相互映射的集合
| Key | Value |
|---|---|
| 1 | Biden |
| 2 | Trump |
有時能用Map就不要用List,查找資訊Map使用效率有時比List要高
//通過HashMap這個實作類來創建一個Map物件
//Students是傳入Key的型別, String是value的型別
Map<Students, String> container = new HashMap<>();
| 常用方法 | 解釋 |
|---|---|
| V put(K key, V value) | 放入鍵值對 |
| Object get(Object Key) | 通過key來獲取值value |
| Set KeySet() | 回傳所有的Key的Set集合 |
| Collection values() | 回傳包含所有值的collection集合 |
| boolean containsKey(Object key) | 如果此映射包含對于指定鍵的映射關系,則回傳 true |
| boolean containsValue(Object Value) | 如果此映射將一個或多個鍵映射到指定值,則回傳 true |
| V remove(Object key) | 如果存在,根據key移除此鍵值對 |
如果有一些方法解釋不全,可以參考以下API鏈接
API: https://www.runoob.com/manual/jdk1.6/
實作Map介面的類有HashMap, TreeMap等
Map遍歷
- KeySet()
Map <String, String> map = new HashMap<>();
Set<String> key = map.KeySet(); //是所有的Key的集合. 隨后可以使用增強for 或迭代器去遍歷
System.out.println("\tKeySet");
for( Students i : container.keySet() )
{
System.out.println(i.getName()+"----"+container.get(i));
}
- EntrySet()
EntrySet()的效率要略高于KeySet()
for(Entry<Students, String> i :container.entrySet())
{
System.out.println(i.getKey().getName()+"----"+i.getValue());
}
HashMap
HashMap和HashSet類似,也是存盤資料的集合;HashSet是存盤值資料,而HashMap是存盤鍵值對資料
在HashMap中Key的資料是根據hashcode來存的
HashMap是無序的,即我們插入和取出的順序是不一樣的
Students案例
由于是根據hashcode來存盤key,我們需要重寫students中的hashcode和equals方法
package Map_Key_Value;
public class Students {
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [ name: "+this.getName()+", age: "+this.getAge()+" ]";
}
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj == null) {
return false;
}
if(obj instanceof Students) {
Students students = (Students) obj;
if(this.name.equals(students.name)&&this.age == students.age) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
//第一種轉換string的方法
// String age = String.valueOf(this.age);
//第二種
// String age = this.age+"";
String age = Integer.toString(this.age);
return age.hashCode()*this.name.hashCode();
}
}
package Map_Key_Value;
import java.util.HashMap;
import java.util.Map.Entry;
public class OriginalMap {
public static void main(String[] args) {
HashMap<Students, String> container = new HashMap<>();
// Students Jim = new Students(18, "Jim");
// container.put(Jim, "CSSE120");
container.put(new Students(18, "Jim"), "CSSE120");
container.put(new Students(20, "John"), "CSSE220");
container.put(new Students(17, "Alex"), "MA112");
container.put(new Students(20, "Eric"), "ESL102");
System.out.print("獲取 Students(18, \"Jim\") 的值:");
System.out.println(container.get(new Students(18, "Jim")));//get value
//遍歷
//使用KeySet方法
System.out.println("\tKeySet遍歷");
for(Students i:container.keySet()) {
System.out.println(i.getName()+"----"+container.get(i));
}
//使用EntrySet方法
System.out.println("\tEntrySet遍歷");
// Set<Map.Entry<Students, String>> entrys = container.entrySet();
for(Entry<Students, String> i : container.entrySet()) {
System.out.println(i.getKey().getName()+"----"+i.getValue());
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rtUa3yt3-1613061611892)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208215330562.png)]
TreeMap
TreeMap存盤資料根據compareTo方法,對于自定義物件需要override比較方法,這個與TreeSet類似
下面就不多解釋了,不懂可以查看API
API: https://www.runoob.com/manual/jdk1.6/
JAVA常用類
java中還有一些常用的工具類,這些類都是日常開發時可能會用到的
Arrays類
Arrays是陣列的意思,Arrays是為陣列所開發的工具類(方法是靜態static方法)
arrays能處理的型別有int, double, long, char等
| 常用方法 | 解釋 |
|---|---|
| static boolean equals(int[ ] a, int[ ] a2) | 如果兩個int型別陣列相等,則回傳true |
| static int hashCode(int[ ] a) | 回傳指定陣列的哈希值 |
| static void sort(double[ ] a) | 對指定陣列進行升序排序 |
| static String toString(char[ ] a) | 將陣列內容轉化為字串 |
| static void sort(T[ ] a, Comparator<? super T> c ) | 根據指定比較器的順序對指定物件陣列進行排序 |
Date和Calendar類
Data和Calendar是java中表示時間的兩個類,它們能回傳當前的時間的毫秒值
毫秒值表示自 1970 年 1 月 1 日 00:00:00 GMT 以來經過的毫秒數,
Date
構造方法
//以當前時間來初始化物件
Date date = new Date();
//建構式接收一個引數,這個引數是從1970年起的毫秒數
Date date = new Date(long millisec)
| 常用方法 | 解釋 |
|---|---|
| String toString() | 格式化日期轉義形式yyyy-mm-dd的日期 |
| int getHours() | 獲取此刻的小時 |
| String toLocaleString() | 回傳當前本地格式的時間(方法已過時) |
package DateAndCalendar;
import java.util.Date;
public class DateDemo1 {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.toString());
System.out.println(date.toLocaleString());
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZHhV2f1Y-1613061611892)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210209130751457.png)]
我們可以使用SimpleDateFormat將日期輸出格式化
| 格式 | 含義 | 例子 |
|---|---|---|
| yyyy | 年 | 2020 |
| MM | 月 | 1 |
| dd | 日 | 22 |
| HH | 24小時制 | 13 |
| hh | 12小時制 | 1 |
| ss | 秒 | 07 |
| S | 毫秒 | 7000 |
| E | 星期幾 | Monday |
| D | 一年中的第幾天 | 365 |
| F | 一個月中的第幾周的周幾 | 2 |
| w | 一年中的第幾周 | 7 |
| W | 一個月中的第幾周 | 2 |
| a | AM / PM | PM |
| z | 時區 | CST |
package DateAndCalendar;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo1 {
public static void main(String[] args) {
Date date = new Date();
// System.out.println(date.toString());
// System.out.println(date.toLocaleString());
SimpleDateFormat Df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(Df.format(date));
}
}
我們還能用時間來做一個定時器
package DajavateAndCalendar;
//在10s之內,持續列印hello, 結束時列印world
public class DateDemo1 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
while(true) {
long end = System.currentTimeMillis();
if((end-start)>10000) {
System.out.println("world");
break;
}
System.out.println("hello");
}
}
}
Calendar
通過Calendar我們可以獲取時間中特定的資料
Calendar類的功能要比Date類強大很多,而且在實作方式上也比Date類要復雜一些,
由于Calendar是protected型別,只能通過其他方法進行構建
static Calendar getInstance()
//使用默認時區獲取日歷
Calendar date = Calendar.getInstance();
在Calendar中,系統定義了一些常量
Calendar.YEAR 年
Calendar.MONTH 月
Calendar.DATE 日期
Calendar.HOUR 小時
Calendar.MINUTE 分鐘
Calendar.SECOND 秒
Calendar.DAY_OF_WEEK 星期幾
常用方法
int get(int field)
calendar.get(Calendar.YEAR)//可用于獲取calendar特定的年-月-日
abstract void add(int field, int amount) //根據日歷給特定的欄位增減時間量
void set(int year, int month, int day, int hourOfDay, int minute, int second)//設定特定值
例子
package DateAndCalendar;
import java.util.Calendar;
import java.util.Date;
public class CalendarDemo1 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH)+1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("Today is "+year+"-"+month+"-"+day);
}
}
JAVA例外處理
在寫程式時我們可能會遇到程式報錯的情況,此時編譯器會出現紅色的提示,如下
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jgGqCjwp-1613061611893)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210209194701662.png)]
這就是例外Exception
所有的例外都是從java.lang.Exception中繼承的,Exception類是Throwable類的子類,Throwable還有一個子類Error
常見例外
- 用戶輸入了非法資料
- 要打開的檔案不存在
- 網路連接通信時中斷,或者JVM記憶體溢位
三大類例外
1. 檢查性例外(checked exception)
如用戶輸入例外或者打開一個不存在的檔案(這些例外在編譯時不能被簡單地忽略)
2. 運行時例外
運行時可能被程式員避免的例外
3. 錯誤
錯誤不是例外,通常是擺脫程式員控制的問題,例如當記憶體溢位時,會報錯誤
檢查性例外
- InterruptedException
一個執行緒被另一個執行緒中斷,拋出該例外, - NoSuchFieldException
請求的變數不存在
非檢查性例外
1. ArithmeticException
2. NumberFormatException
當應用程式試圖將字串轉換成一種數值型別,但該字串不能轉換為適當格式時,拋出該例外
3. NullPointerException
4. IndexOutOfBoundsException
遍歷超過
5. UnsupportedOperationException
捕獲例外
//捕獲例外的基礎語法
try{
}catch(IOException e1){
//如何處理該例外,例外e1的型別可以為Exception的子類或Exception;
}catch(ArithmeticException e2){
}finally{
//finally可加可不加
//如果加了,無論是否發生例外,finally 代碼塊中的代碼總會被執行,
//一般這里用于釋放記憶體,如input.close()
}
例子
我們要用戶輸入兩個數并互除,在除法中,被除數不能為0,所以我們要捕獲這個例外
package Exception;
import java.util.Scanner;
public class ExceptionStudyDemo1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
System.out.print("Num1: ");
int num = input.nextInt();
System.out.print("Num2: ");
int num2 = input.nextInt();
//注意此時num/num2得出的數字是整數
System.out.println("Num1 / Num2 = "+num/num2);
}
catch(ArithmeticException a) {
System.out.println(a.getMessage()); //獲取為什么錯誤
}
finally {
input.close();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HCb0goWT-1613061611894)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211155159674.png)]
解決方法
添加一個
double rst = num*1.0/num2;java
package Exception;
import java.util.Scanner;
public class ExceptionStudyDemo1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
System.out.print("Num1: ");
int num = input.nextInt();
System.out.print("Num2: ");
int num2 = input.nextInt();
double rst = num*1.0/num2;
System.out.println("Num1 / Num2 = "+rst);
}
catch(ArithmeticException a) {
System.out.println(a.getMessage());
}
finally {
input.close();
}
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qNDO2WYq-1613061611895)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211155458450.png)]
Throws 關鍵字
throws中文意思是拋出,當一個函式有一個例外,此時我們不想處理時,我們可以throws這個Exception,交給函式外的部分處理
還是剛才num / num2的例子
package Exception;
import java.util.Scanner;
public class ExceptionStudyDemo1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
System.out.print("Num1: ");
int num = input.nextInt();
System.out.print("Num2: ");
int num2 = input.nextInt();
divide(num, num2);
}
catch(ArithmeticException a) {
System.out.println(a.getMessage());
}
finally {
input.close();
}
}
public static void divide(int num, int num2) throws ArithmeticException{
System.out.println("Num1 / Num2 = "+num/num2);
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VOPcrIp5-1613061611895)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211160006853.png)]
自定義例外類
所有例外必須是Throwable的子類,如果希望寫一個檢查性例外,則需要繼承Exception類;如果是運行時例外,則繼承RuntimeException類
繼承語法
class CustomException extends Exception{
//里面根據編譯器自動生成
}
package Exception;
import java.util.Scanner;
public class ExceptionStudyDemo1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
System.out.print("Num1: ");
int num = input.nextInt();
System.out.print("Num2: ");
int num2 = input.nextInt();
divide(num, num2);
}
catch(CustomException a){
//捕獲自定義例外
}
public static void divide(int num, int num2) throws CustomException{ //在方法中拋出例外
if(num2 == 0) {
throw new CustomException(); //在方法中加入此陳述句,即為判斷那種情況下拋出自定義例外
}
}
}
自定義例外有什么用呢?
當我們自己開發時,有時需要自己定義一些例外(別人能看懂的例外類名字),這樣可以方便開發
JAVA IO處理
我們每次運行一個程式,此時我們輸入的資料僅僅是存在快取中的,倘若我們關掉程式,資料就會隨之消失,為了把資料存起來,我們需要學習IO處理(Input Output),這樣資料才可以寫入記憶體硬碟里面,
流的概念
流stream可以為資料與目的之間建立通道,通過流我們可以把在記憶體中的資訊寫入到硬碟中;同理,我們也可以將硬碟中的資料讀取,print在控制臺里面
通過流讀取的不管是位元組還是字符,一般回傳的都是int值
流的分類
流有很多種類,按照處理資料側重點的不同可以分為輸入/輸出位元組流與輸入/輸出字符流;
這里我參考某位博主的圖片來解釋:https://blog.csdn.net/mu_wind/article/details/108674284

位元組流
位元組流每次讀取或寫入一個位元組,2字符=1位元組, 1位元組(Byte) = 8位 (bit),位元組流可以處理影像,視頻等
一般英文字母一個字母為一個位元組(位元組是以int型別表示而字母則是以char型別表示)
字符流
字符流每次讀取或寫入一個字符,字符流只能用于處理文字資訊
中文與英文有點區別,1個中文代表1個字符(char),1個字符 = 2個位元組, 加入用位元組流讀取中文字符會出現亂碼
流的使用
位元組流使用
輸入位元組流
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wjOhF8K1-1613061611896)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211224816778.png)]
//實體化物件
FileInputStream file = new FileInputStream("E:\\java程式\\ReadFile.txt");
//讀取檔案內容
//讀取出來的是位元組流資訊,要轉化成char或string才能列印
//file.read()一次讀取一個位元組,如果有回傳此位元組,若沒有回傳-1
int data;
while((data = file.read()) != -1) {
System.out.print((char)data);
}
//使用自制緩沖區讀取資料
byte[] buffer = new byte[3];//自制的一次能儲存3個位元組的緩沖區
int count=0;
while((count = file.read(buffer))!=-1) {
System.out.print(new String(buffer,0,count));
}
//注意打開的檔案使用后要關閉
file.close();
輸出位元組流
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DSBb74TV-1613061611898)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211224920029.png)]
//實體化物件
//true表示如果給出的檔案地址已存在,則在此檔案的基礎上再寫如內容
FileOutputStream Out = new FileOutputStream("E:\\java程式\\OutPutFile.txt",true);
//寫入內容
String words = "HELLO WORLD ";
Out.write(words.getBytes()); //通過位元組流來寫入,必須是位元組形式
//同樣,寫完記得關閉
Out.close();
由于普通的輸入輸出位元組流效率不高,一般需要與緩沖流相互配合
檔案內容先讀入緩沖區,接著被程式訪問,這樣可以減少程式訪問硬碟的次數
緩沖輸入輸出流
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tZ7vrIER-1613061611899)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211225026578.png)]
//使用緩沖區讀取資料
FileInputStream file = new FileInputStream("E:\\java程式\\ReadFile.txt");
BufferedInputStream buf = new BufferedInputStream(file);
int data;
while((data = buf.read()) != -1) {
System.out.print((char)data);
}
//緩沖區用完也最好記得關閉
buf.close();
//使用緩沖區輸出資料
package IOStudy;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
public class buf {
public static void main(String[] args) throws Exception {
System.out.println("hello world");
FileOutputStream file = new FileOutputStream("E:\\java程式\\BufferOutput.txt",true);
BufferedOutputStream buf = new BufferedOutputStream(file);
for(int i=0;i<4;i++) {
buf.write("hello world ".getBytes());
buf.flush(); //使用緩沖區每寫入一次資料要重繪一遍
}
System.out.println("Finish");
buf.close();
}
}
物件流與序列化
位元組流可以傳輸任何資料型別,包括物件,由此產生了另一個流,物件流
創建方法
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(source, true));
ObjectInputStream 讀取Obj資料順序根據寫入順序來,先進先出
在使用物件流寫入物件資料時,該物件必須實作Serializable介面
之前介面部分有提到Serializable沒有任何方法和常量,它是一個標記類
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SMPV6LNC-1613061611899)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211225831552.png)]
下面我們要將兩個學生類的資訊儲存到硬碟中,再通過一個程式將內容讀取出來
//學生類,要實作Serializable介面
package IOStudy;
import java.io.Serializable;
public class Student implements Serializable{
/**
*
*/
private static final long serialVersionUID = -4870784691100550826L;
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "["+this.getName()+" , "+this.getAge()+"]";
}
}
//寫入資訊
package IOStudy;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class ObjectWrite {
public static void main(String[] args) throws Exception{
String source = "E:\\java程式\\ObjWriter.bin";
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(source));
Student Biden = new Student("Biden", 78);
Student Trump = new Student("Trump", 72);
obj.writeObject(Trump);
obj.writeObject(Biden);
obj.writeObject(null);
obj.close();
System.out.println("Finish");
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3t55wuuK-1613061611900)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000040489.png)]
//讀取資訊
package IOStudy;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class ObjectRead {
public static void main(String[] args) throws Exception{
String source ="E:\\java程式\\ObjWriter.bin";
ObjectInputStream obj = new ObjectInputStream(new FileInputStream(source));
Object stu;
while((stu=obj.readObject())!= null) {
System.out.println(stu);
}
obj.close();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5g4mgD9P-1613061611901)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000057958.png)]
字符流使用
字符流輸入輸出
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Q0B1QXiv-1613061611901)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211225130652.png)]
//實體化物件
FileReader read = new FileReader(Source);
//讀取操作與位元組流類似
//案例(反例),我們使用默認的解碼格式讀取資料
package IOStudy;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
public class ReadFile2 {
public static void main(String[] args) throws Exception{
String Source = "E:\\java程式\\字符Reader.txt";
FileReader read = new FileReader(Source);
int count =0;
while((count = read.read())!= -1) {
System.out.print((char)count);
}
read.close();
}
}
結果,中文出現亂碼
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9Mfg0ljR-1613061611903)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211232655649.png)]
由于英文一個字母只占一個位元組,默認的GBK解碼沒有問題,但是中文一個字占3個位元組,使用GBK解碼(與文本保存的格式不同)出現了亂碼,
為了保證能正確解碼,我們讀取字符檔案時要指定解碼格式,例如UTF-8
//下面是對上面例子的修改
package IOStudy;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
public class ReadFile2 {
public static void main(String[] args) throws Exception{
String Source = "E:\\java程式\\字符Reader.txt";
InputStreamReader read = new InputStreamReader(new FileInputStream(Source),"UTF-8");
int count =0;
while((count = read.read())!= -1) {
System.out.print((char)count);
}
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cmLS8dzw-1613061611903)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211233135453.png)]
中文字符流寫出時,不用擔心上面編碼的問題,系統默認是GBK編碼,例子如下
package IOStudy;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
public class WriteFile2 {
public static void main(String[] args) throws Exception{
String Source = "E:\\java程式\\字符Writer.txt";
FileWriter file = new FileWriter(Source);
file.write(" 世界你好 ");
System.out.println("Finish");
file.close();
}
}
寫入的結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Fl8HL4f9-1613061611903)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211233838187.png)]
ANSI就是GBK編碼格式
當然,我們也可以指定輸出格式,像輸入一樣
package IOStudy;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
public class WriteFile2 {
public static void main(String[] args) throws Exception{
String Source = "E:\\java程式\\字符Writer.txt";
OutputStreamWriter file = new OutputStreamWriter(new FileOutputStream(Source,true), "UTF-8");
// FileWriter file = new FileWriter(Source);
file.write(" 世界你好 ");
System.out.println("Finish");
file.close();
}
}
結果:檔案使用UTF-8編碼格式
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yYUtAIF2-1613061611904)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211234107217.png)]
字符流讀取緩沖流
package IOStudy;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class BufferCharRead {
public static void main(String[] args) throws Exception{
String source = "E:\\編程.txt";
BufferedReader buf = new BufferedReader(new InputStreamReader(new FileInputStream(source), "GBK"));
for(int i=0;i<20;i++)//列印緩沖區中的前20行
//buf.readLine()指讀一行資料
System.out.println(buf.readLine());
buf.close();
}
}
檔案夾操作
java的IO處理還包括檔案夾的一些操作,例如檔案夾的創建,洗掉等
//構造方法
//--1--
File file = new File(String parent_path, String child_path);
//--2--
File file = new File(String absolute_path)
| 目錄操作 | 解釋 |
|---|---|
| createNewFile() | 創建一個新檔案,不是檔案夾 |
| mkdir() | 創建一個新目錄 |
| delete() | 洗掉檔案或空目錄 |
| exists() | 判斷File物件所表示的物件是否存在 |
| getAbsolutePath() | 獲取檔案的絕對路徑 |
| getName() | 獲取目錄的名字 |
| getParent() | 獲取檔案/目錄所在的目錄, 該檔案夾所在絕對路徑E:\java程式\PicSource\Summer_Pocket Parent就是E:\java程式\PicSource Child就是Summer_Pocket |
| isDirectory() | 判斷是否是目錄 |
| isFile() | 判斷是否是檔案 |
| length() | 獲取檔案的長度,以位元組為單位 |
| renameTo() | 修改檔案名為 |
| listFiles() | 列出目錄中的所有內容 File[] files = file.listFiles(); 回傳的是File型別陣列 File[] file2 = file.listFiles(FileFilter filter);//可以通過Filefilter進行過濾檔案的目的 |
FileFilter介面
public interface FileFilter
//需要實作的方法
boolean accept(File pathname)
案例
存了一些圖片在某個檔案夾中,我們要將這些圖片重命名,按1-50的順序重命名
package IOStudy;
import java.io.File;
import java.io.FileFilter;
import java.util.Scanner;
public class FileOperator {
public static void main(String[] args) throws Exception {
File file = new File("E:\\java程式\\PicSource");
System.out.println("dictory's name: "+file.getName());
File[] files = file.listFiles();
Integer count =0;
for(File pic:files) {
File image = new File(file.getAbsolutePath(),count.toString()+".jpg");
if(pic.isFile()) {
pic.renameTo(image);
count++;
}
}
File[] file2 = file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith(".jpg"))
return true;
return false;
}
});
for(File pic:file2) {
System.out.println(pic.getName());
}
}
}
結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fqe9AdYz-1613061611905)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212002426056.png)]
Properties
properties是一個屬性集合,繼承HashTable,是一個執行緒安全的集合;properties可以儲存鍵值對,同時鍵值對是字串型別,它沒有泛型,
//構造方法
Properties container = new Properties();
//常用方法
container.setProperty("Trump","72");
//使用迭代器遍歷properties中的鍵值對
Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();
while(itr.hasNext()) {
Entry<Object, Object> set = itr.next();
System.out.println(set.getKey()+"=====>"+set.getValue());
}
//使用Set遍歷鍵值對
Set<String> set = container.stringPropertyNames();
for(String pro:set) {
System.out.println(pro+"=====>"+container.getProperty(pro));
}
//load加載存盤在硬碟中property的內容
container.load(FileInputStream fis);
//以適合的方法將鍵值對寫入到輸出流,可以保存注釋
container.store(FileOutputStream fos, String comment);
//-----//
//store方法,以適合的方法將鍵值對寫入到輸出流,可以保存注釋
FileOutputStream fos = new FileOutputStream("E:\\java程式\\properties_save.txt");
container.store(fos, "American President");
fos.close();
//----//
//將屬性串列輸出到指定的輸出流
container.list(PrintWriter file);
舉一個儲存properties的例子
package IOStudy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
public class PropertyStudy {
public static void main(String[] args) throws Exception {
Properties container = new Properties();
container.setProperty("Trump", "72");
container.setProperty("Biden", "74");
System.out.println(container.getProperty("Trump"));
//使用迭代器遍歷
Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();
while(itr.hasNext()) {
Entry<Object, Object> set = itr.next();
System.out.println(set.getKey()+"=====>"+set.getValue());
}
//將屬性串列輸出到指定的輸出流
PrintWriter file =new PrintWriter(new FileOutputStream("E:\\java程式\\properties_save.txt"));
container.list(file);
file.close();
}
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qPwJjFAh-1613061611907)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000516493.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rRe7NZqH-1613061611908)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000544377.png)]
讀取properties在硬碟中的內容
//load加載properties內容
FileInputStream fis = new FileInputStream("E:\\java程式\\properties_save.txt");
container.load(fis);
fis.close();
Set<String> set = container.stringPropertyNames();
for(String pro:set) {
System.out.println(pro+"=====>"+container.getProperty(pro));
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2oIxvIii-1613061611908)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000811298.png)]
參考文獻
API:https://www.runoob.com/manual/jdk1.6/
菜鳥教程:https://www.runoob.com/java/java-tutorial.html
JAVA final關鍵字:https://blog.csdn.net/PickUpOldDriver/article/details/80566628
JAVA static block:https://blog.csdn.net/qq_35868412/article/details/89360250
JAVA this關鍵字:https://blog.csdn.net/qq_43555323/article/details/84993460
JAVA IO:https://blog.csdn.net/baobeiSimple/article/details/1713797
BufferedReader(new InputStreamReader(new FileInputStream(source), “GBK”));
for(int i=0;i<20;i++)//列印緩沖區中的前20行
//buf.readLine()指讀一行資料
System.out.println(buf.readLine());
buf.close();
}
}
### 檔案夾操作
java的IO處理還包括檔案夾的一些操作,例如檔案夾的創建,洗掉等
```java
//構造方法
//--1--
File file = new File(String parent_path, String child_path);
//--2--
File file = new File(String absolute_path)
| 目錄操作 | 解釋 |
|---|---|
| createNewFile() | 創建一個新檔案,不是檔案夾 |
| mkdir() | 創建一個新目錄 |
| delete() | 洗掉檔案或空目錄 |
| exists() | 判斷File物件所表示的物件是否存在 |
| getAbsolutePath() | 獲取檔案的絕對路徑 |
| getName() | 獲取目錄的名字 |
| getParent() | 獲取檔案/目錄所在的目錄, 該檔案夾所在絕對路徑E:\java程式\PicSource\Summer_Pocket Parent就是E:\java程式\PicSource Child就是Summer_Pocket |
| isDirectory() | 判斷是否是目錄 |
| isFile() | 判斷是否是檔案 |
| length() | 獲取檔案的長度,以位元組為單位 |
| renameTo() | 修改檔案名為 |
| listFiles() | 列出目錄中的所有內容 File[] files = file.listFiles(); 回傳的是File型別陣列 File[] file2 = file.listFiles(FileFilter filter);//可以通過Filefilter進行過濾檔案的目的 |
FileFilter介面
public interface FileFilter
//需要實作的方法
boolean accept(File pathname)
案例
存了一些圖片在某個檔案夾中,我們要將這些圖片重命名,按1-50的順序重命名
package IOStudy;
import java.io.File;
import java.io.FileFilter;
import java.util.Scanner;
public class FileOperator {
public static void main(String[] args) throws Exception {
File file = new File("E:\\java程式\\PicSource");
System.out.println("dictory's name: "+file.getName());
File[] files = file.listFiles();
Integer count =0;
for(File pic:files) {
File image = new File(file.getAbsolutePath(),count.toString()+".jpg");
if(pic.isFile()) {
pic.renameTo(image);
count++;
}
}
File[] file2 = file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith(".jpg"))
return true;
return false;
}
});
for(File pic:file2) {
System.out.println(pic.getName());
}
}
}
結果
[外鏈圖片轉存中…(img-fqe9AdYz-1613061611905)]
Properties
properties是一個屬性集合,繼承HashTable,是一個執行緒安全的集合;properties可以儲存鍵值對,同時鍵值對是字串型別,它沒有泛型,
//構造方法
Properties container = new Properties();
//常用方法
container.setProperty("Trump","72");
//使用迭代器遍歷properties中的鍵值對
Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();
while(itr.hasNext()) {
Entry<Object, Object> set = itr.next();
System.out.println(set.getKey()+"=====>"+set.getValue());
}
//使用Set遍歷鍵值對
Set<String> set = container.stringPropertyNames();
for(String pro:set) {
System.out.println(pro+"=====>"+container.getProperty(pro));
}
//load加載存盤在硬碟中property的內容
container.load(FileInputStream fis);
//以適合的方法將鍵值對寫入到輸出流,可以保存注釋
container.store(FileOutputStream fos, String comment);
//-----//
//store方法,以適合的方法將鍵值對寫入到輸出流,可以保存注釋
FileOutputStream fos = new FileOutputStream("E:\\java程式\\properties_save.txt");
container.store(fos, "American President");
fos.close();
//----//
//將屬性串列輸出到指定的輸出流
container.list(PrintWriter file);
舉一個儲存properties的例子
package IOStudy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
public class PropertyStudy {
public static void main(String[] args) throws Exception {
Properties container = new Properties();
container.setProperty("Trump", "72");
container.setProperty("Biden", "74");
System.out.println(container.getProperty("Trump"));
//使用迭代器遍歷
Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();
while(itr.hasNext()) {
Entry<Object, Object> set = itr.next();
System.out.println(set.getKey()+"=====>"+set.getValue());
}
//將屬性串列輸出到指定的輸出流
PrintWriter file =new PrintWriter(new FileOutputStream("E:\\java程式\\properties_save.txt"));
container.list(file);
file.close();
}
}
[外鏈圖片轉存中…(img-qPwJjFAh-1613061611907)]
[外鏈圖片轉存中…(img-rRe7NZqH-1613061611908)]
讀取properties在硬碟中的內容
//load加載properties內容
FileInputStream fis = new FileInputStream("E:\\java程式\\properties_save.txt");
container.load(fis);
fis.close();
Set<String> set = container.stringPropertyNames();
for(String pro:set) {
System.out.println(pro+"=====>"+container.getProperty(pro));
}
[外鏈圖片轉存中…(img-2oIxvIii-1613061611908)]
參考文獻
API:https://www.runoob.com/manual/jdk1.6/
菜鳥教程:https://www.runoob.com/java/java-tutorial.html
JAVA final關鍵字:https://blog.csdn.net/PickUpOldDriver/article/details/80566628
JAVA static block:https://blog.csdn.net/qq_35868412/article/details/89360250
JAVA this關鍵字:https://blog.csdn.net/qq_43555323/article/details/84993460
JAVA IO:https://blog.csdn.net/baobeiSimple/article/details/1713797
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/259276.html
標籤:其他
下一篇:常用設計模式概覽
