類
類的源文件名必須與類同名郁季。對于所有的類來說,類名的首字母應(yīng)該大寫钱磅。
如果沒有顯式為一個類指定構(gòu)造方法梦裂,編譯器會默認(rèn)提供。
在創(chuàng)建一個類對象的時候盖淡,必須要有構(gòu)造方法年柠,類的構(gòu)造方法名必須與類同名,且可以有多個禁舷。Java
中使用new
關(guān)鍵字創(chuàng)建對象彪杉。
一個Java
的源文件只能有一個Public
類毅往,但可以有多個非Public
的類牵咙。源文件的名稱需與Public
的類的類名保持一致派近。
Package
主要用來對Java
中眾多的類、接口進(jìn)行分類洁桌。
如果一個類定義在某個包中渴丸,那么 package
語句應(yīng)該在源文件的首行。
包名通常使用小寫的字母來命名避免與類另凌、接口名字的沖突谱轨。
創(chuàng)建包:
///創(chuàng)建 ` learn.cls`的包
package learn.cls;
public class Person {
}
//在包中加入`Student`類,獨立的源文件
package learn.cls;
public class Student extends Person {
}
包名必須要有與之對應(yīng)的文件目錄結(jié)構(gòu):
learn.cls
則必須要有learn/cls
這樣的目錄結(jié)構(gòu)吠谢。
import
import
+ 路徑 (包名土童,類名),用以定位類或源代碼工坊。
import learn.cls.*
編譯器會從ClASSPATH/learn/cls
目錄下查找對應(yīng)的類献汗。
如果源文件包含 import
語句,那么應(yīng)該放在 package
語句和類定義之間王污。如果沒有 package
語句罢吃,那么import
語句應(yīng)該在源文件中最前面。
import
語句和 package
語句對源文件中定義的所有類都有效昭齐。在同一源文件中尿招,不能給不同的類不同的包聲明。
基本數(shù)據(jù)類型
Java
有兩大數(shù)據(jù)類型
- 內(nèi)置數(shù)據(jù)類型
- 引用數(shù)據(jù)類型
內(nèi)置數(shù)據(jù)類型
有8種基本數(shù)據(jù)類型:
四種整型:
byte
: 8
位有符號的整數(shù) 范圍 -128 ~ 127
short
: 16
位有符號的整數(shù) 范圍 -2^15 ~ 2^15 - 1
int
: 32
位有符號的整數(shù) 范圍 -2^31 ~ 2^31 - 1
long
: 64
位有符號的整數(shù) 范圍 -2^63 ~ 2^63 - 1
兩種浮點數(shù):
float
: 單精度阱驾,32
位 小數(shù)
double
: 雙精度就谜,64
位 小數(shù)
其他:
boolean
: true
or false
char
: 單一的 16
位Unicode
字符
引用類型
對象、數(shù)組都是引用數(shù)據(jù)類型里覆。
所有引用類型的默認(rèn)值都是null
吁伺。
一個引用變量可以用來引用任何與之兼容的類型。
Java常量
在 Java
中使用final
關(guān)鍵字來修飾常量租谈,聲明方式和變量類似:
final double PI = 3.1415927;
byte篮奄、int、long割去、short
都可以用十進(jìn)制窟却、16
進(jìn)制以及8
進(jìn)制的方式來表示。
當(dāng)使用字面量的時候呻逆,前綴 0
表示 8
進(jìn)制夸赫,而前綴 0x
代表 16 進(jìn)制, 例如:
int decimal = 100;
int octal = 0144;
int hexa = 0x64;
字符串常量和字符常量都可以包含任何Unicode
字符。例如:
char a = '\u0001';
String a = "\u0001";
自動類型轉(zhuǎn)換
整型咖城、實型(常量)茬腿、字符型數(shù)據(jù)可以混合運算呼奢。運算中,不同類型的數(shù)據(jù)先轉(zhuǎn)化為同一類型切平,然后進(jìn)行運算握础。
轉(zhuǎn)換順序由低到高依次為:
byte, short, char -> int->long->float->double
數(shù)據(jù)類型轉(zhuǎn)換必須滿足如下規(guī)則:
- 不能對boolean類型進(jìn)行類型轉(zhuǎn)換。
- 不能把對象類型轉(zhuǎn)換成不相關(guān)類的對象悴品。
- 在把容量大的類型轉(zhuǎn)換為容量小的類型時必須使用強制類型轉(zhuǎn)換禀综。
- 浮點數(shù)到整數(shù)的轉(zhuǎn)換是通過舍棄小數(shù)得到,而不是四舍五入.
強制類型轉(zhuǎn)換
int x = 128;
byte y = (byte) x; // y = -128 位數(shù)不足苔严,溢出
double d = 7.9D;
int e = (int)d; //7
整數(shù)的默認(rèn)類型為int
;
小數(shù)默認(rèn)是 double
類型定枷,在定義 float
類型時必須在數(shù)字后面跟上 F
或者 f
。
Java的變量
Java
中變量的聲明與其他語言大同小異届氢,基本都是 Type Identifier = value
欠窒。
局部變量
局部變量不會有默認(rèn)值,訪問修飾符也不能作用于局部變量退子,必須初始化才能使用
public void pupAge(){
///錯誤
int age;
///正確
int age = 0;
age = age + 7;
System.out.println("小狗的年齡是 : " + age);
}
實例變量
當(dāng)一個對象被實例化之后侣夷,每個實例變量的值就跟著確定窿给;實例變量在對象創(chuàng)建的時候創(chuàng)建组橄,在對象被銷毀的時候銷毀帆赢;實例變量可以聲明在使用前或者使用后;訪問修飾符可以修飾實例變量壤靶;實例變量具有默認(rèn)值缚俏。數(shù)值型變量的默認(rèn)值是0
,布爾型變量的默認(rèn)值是false
贮乳,引用類型變量的默認(rèn)值是null
忧换。變量的值可以在聲明時指定,也可以在構(gòu)造方法中指定向拆;
Java的修飾符
Java
中的修飾符有兩種:
訪問修飾符
用來對類亚茬、方法、構(gòu)造方法浓恳、變量的訪問設(shè)置不同的權(quán)限刹缝。
- public : 范圍:所有類可見;修飾對象:類颈将、方法梢夯、接口、變量
- protected : 范圍:同一包中的類和所有子類可見晴圾,修飾對象:方法颂砸、變量;不能修飾類
- private:范圍:同一類內(nèi)可見,修飾對象:方法人乓、變量勤篮;不能修飾類
- default:默認(rèn)訪問修飾符,不使用任何關(guān)鍵字色罚;同一包中可見碰缔;修飾對象:類、接口保屯、方法手负、變量涤垫。
接口里的變量都隱式聲明為 public static final
,而接口里的方法默認(rèn)情況下訪問權(quán)限為 public
姑尺。
protected
修飾符有個兩個點需要分析說明:
- 子類與基類在同一個包內(nèi),被聲明為
protected
的變量蝠猬、方法和構(gòu)造器能被同一個包中的任何其他類訪問切蟋。 - 子類與子類不在同一個包內(nèi),那么在子類中榆芦,子類實例可以訪問其從基類繼承而來的
protected
方法柄粹,而不能訪問基類實例的protected
方法。示例:
///基類在包`Animals `中
package Animals;
public class Animals {
protected void run() {
System.out.print("跑");
}
protected void eat() {
System.out.print("吃飯");
}
}
///子類在包 learn.cls中
package learn.cls;
import Animals.Animals;
public class Dog extends Animals {
@Override
protected void eat() {
this.run();
System.out.print("吃屎");
}
}
// 在包learn.cls的其他類中創(chuàng)建Dog實例并訪問基類被protected修飾的方法
Dog dog = new Dog();
dog.eat(); ///?
dog.run();//無法訪問匆绣,編譯器會報錯 ?
///但是基類的run方法在子類是可在直接訪問的驻右,
子類能訪問 protected
修飾符聲明的方法和變量,這樣就能保護(hù)不相關(guān)的類使用這些方法和變量崎淳。如果我們只想讓該方法對其所在類的子類可見堪夭,則將該方法聲明為 protected
。
訪問控制和方法繼承規(guī)則
- 父類聲明的
public
方法拣凹,在子類中也必須為public
; - 父類聲明的
protected
方法森爽,在子類中要么為Public
,要么protected
但不能為private
- 父類聲明的
private
方法嚣镜,不能被子類繼承爬迟;
非訪問修飾符
-
static
修飾符,用來修飾類方法和類變量菊匿。 -
final
修飾符付呕,用來修飾類、方法和變量跌捆,final 修飾的類不能夠被繼承徽职,修飾的方法不能被繼承類重新定義,修飾的變量為常量疹蛉,是不可修改的活箕。 -
abstract
修飾符,用來創(chuàng)建抽象類和抽象方法。如果一個類包含抽象方法育韩,那么該類一定要聲明為抽象類克蚂。 -
synchronized
和volatile
修飾符,主要用于線程的編程筋讨。
synchronized
關(guān)鍵字聲明的方法同一時間只能被一個線程訪問埃叭。synchronized
修飾符可以應(yīng)用于四個訪問修飾符。
volatile
修飾的成員變量在每次被線程訪問時悉罕,都強制從共享內(nèi)存中重新讀取該成員變量的值赤屋。而且,當(dāng)成員變量發(fā)生變化時壁袄,會強制線程將變化值回寫到共享內(nèi)存类早。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值嗜逻。
一個 volatile
對象引用可能是null
涩僻。
///`synchronized `
public synchronized void showDetails(){
.......
}
///`volatile `
private volatile boolean active;
transient
修飾符:序列化的對象包含被 transient
修飾的實例變量時,java
虛擬機(JVM)跳過該特定的變量栈顷。即:用它修飾的變量被序列化不會被持久化逆日。
抽象方法是一種沒有任何實現(xiàn)的方法,該方法的具體實現(xiàn)由子類提供萄凤。抽象方法不能被聲明成 final
和 static
室抽。任何繼承抽象類的子類必須實現(xiàn)父類的所有抽象方法,除非該子類也是抽象類靡努。
如果一個類包含若干個抽象方法坪圾,那么該類必須聲明為抽象類。抽象類可以不包含抽象方法颤难。
抽象方法的聲明以分號結(jié)尾神年,例如:public abstract sample();
。
Java 運算符
Java
中的運算符與其他語言運算符基本一致行嗤,分為:
- 算數(shù)運算符
- 自增/減運算符:a++已日、a--、++a栅屏、--a
- 關(guān)系運算符
- 位運算符: 與運算
同1 ? 1 : 0
或運算:同0 飘千? 0 : 1
異或位值相同 ? 0 : 1
- 邏輯運算符
- 賦值運算符
- 條件運算符栈雳、三元運算符
特有的運算符:
instanceof
運算符: 該運算符用于操作對象實例护奈,檢查該對象是否是一個特定類型(類類型或接口類型)。 運算符使用的格式: ( Object reference variable ) instanceof (class/interface type)
boolean istrue = "abcd" instanceof String; // result: true
Java的循環(huán)結(jié)構(gòu)
Java
中有三種主要的循環(huán)結(jié)構(gòu)哥纫,和其他語言一致霉旗,分為:
-
while
循環(huán) -
do…while
循環(huán) -
for
循環(huán)
其中for
循環(huán)在Java
中另一種使用方式:增強for
循環(huán):
int[] numbers = {1,2,3,4,5};
for(int item : numbers) {
System.out.println(item);
}
Java的Number與Math
Numer
:將基本數(shù)據(jù)類型的包裝成類,java
中的基本數(shù)據(jù)類型都有自己的包裝類。
///左側(cè):基本數(shù)據(jù)類型
///右側(cè):包裝后的類
byte -> Byte //extends Number extends Object
short -> Short //extends Number extends Object
int -> Integer //extends Number extends Object
long -> Long //extends Number extends Object
float -> Float //extends Number extends Object
double -> Double //extends Number extends Object
boolean -> Boolean //extends Object
char -> Character //extends Object
Boolean boolobj = Boolean.TRUE;
Character charobj1 = 'e'; //e
Character charobj2 = '\u0065'; //e
System.out.println(charobj);
關(guān)于運算
Integer x = 5;
int y = 10
x = x + y;
System.out.println(x); //15
關(guān)于Math
int a = -10;
Integer b = -40;
a = Math.abs(a);
b = Math.abs(b);
a = a + b;
System.out.println(a); // 50
Java中的Character
Character
類用于對單個字符進(jìn)行操作厌秒。
將一個char
類型的參數(shù)傳遞給需要一個Character
類型參數(shù)的方法時读拆,那么編譯器會自動地將char
類型參數(shù)轉(zhuǎn)換為Character
對象
Character charobj1 = 'e'; //e
Character charobj2 = '\u0065'; //e
if (Character.isDigit(charobj1)) {
System.out.println("是數(shù)字");
}
String str = Character.toString(charobj2);
System.out.println(str);//e
Java中的字符串
- 創(chuàng)建字符串
String string = "String"; /// 存儲在公共池
String heapStr = new String("String"); /// 存儲在堆中
char[] chars = {'h','e','l','l','o'};
String heapStrByChar = new String(chars);
System.out.printf("公共池:%s,堆字符串:%s\n",string,heapStrByChar);//公共池:String,堆字符串:hello
- 字符串操作
///獲取字符串長度
int length = heapStrByChar.length();/// 5
///拼接兩個字符串
string = heapStrByChar.concat(string); //Stringhello
///字符串格式化
String format = String.format("公共池:%s,堆字符串:%s\n",string,heapStrByChar);
System.out.println(format);
注意:String
類是不可改變的,所以一旦創(chuàng)建了 String
對象鸵闪,那它的值就無法改變了
如果需要改變需要用到StringBuffer
和StringBuilder
///StringBuilder
///參數(shù)提示 cmd + p
StringBuilder sb = new StringBuilder(10);
sb.append("hello");
sb.insert(5,'!');
sb.append(new char[]{'B','o','b'});
System.out.println(sb);//hello!Bob
sb.delete(3,6);
String finalStr = sb.toString();
System.out.println(finalStr);///helBob
///StringBuffer
StringBuffer sbf = new StringBuffer("hello");
sbf.append('!');
sbf.append(new char[]{'j','a','v','a'});
sbf.insert(0,"smile");
sbf.insert(5,' ');
System.out.println(sbf);//smile hello!java
sbf.deleteCharAt(11);
String res = sbf.toString();
System.out.println(res);//smile hellojava
StringBuilder
類在 Java 5
中被提出檐晕,它和 StringBuffe
r 之間的最大不同在于 StringBuilder
的方法不是線程安全的(不能同步訪問)。
由于 StringBuilder
相較于 StringBuffer
有速度優(yōu)勢蚌讼,所以多數(shù)情況下建議使用 StringBuilder
類辟灰。
Java數(shù)組
- 數(shù)組聲明
///首選
dataType [] arrayVar;
///效果一致,非首選
dataType arrayVar[];
- 數(shù)組的創(chuàng)建
int[] array = new int[10];
array[0] = 1;
array[1] = 2;
int[] array = {1,2,3,4,4,5};
for (int x : array) {
System.out.println(x);
}
- 多維數(shù)組聲明
///格式
type[][] typeName = new type[typeLength1][typeLength2];
///示例 2行3列的二維整型數(shù)組
int[][] intArray = new int[2][3];
- 多維數(shù)組的創(chuàng)建
int[] arr = {1,2,3};
int[][] array1 = new int[2][3];
array1[1][0] = 2;
array1[1][1] = 3;
array1[1][2] = 4;
array1[0] = arr;
for (int[] item : array1) {
for (int x : item) {
System.out.println(x);
}
}
- 通過
Arrays
類的類方法篡石,執(zhí)行對數(shù)組的操作
int[] array = {1,2,3,4,4,5};
int[] arr = {1,2,3};
Arrays.sort(array);
Arrays.equals(array,arr);
///...
Java日期
-
Date
日期創(chuàng)建
Date date = new Date();
///y:1900 + 119 = 2019 ; m: 0~11
Date date1 = new Date(119,10,20);
// 1$ 表示第一個參數(shù) %t 表示打印時間 %n 換行 %tF 表示以格式`%tY-%tm-%td`輸出日 %tb/%tB 月份的全稱與簡稱
System.out.printf("%1$tY:%1$tm:%1$td %1$tB%n %2$tF%n",date,date1);
///2022:02:17 二月
///2019-11-20
-
Date
日期格式化
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String tfs = df.format(date);
System.out.println(tfs);
- 字符串轉(zhuǎn)日期
Date
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = "2022-10-01";
try {
Date date2 = df1.parse(dateStr);
System.out.printf("%tD%n",date2);//10/01/22
} catch (ParseException e) {
System.out.println("解析出錯");
}
日期格式化輸出
詳見:https://www.runoob.com/w3cnote/java-printf-formate-demo.htmlCalendar
的創(chuàng)建與使用
Calendar
類是一個抽象類芥喇,在實際使用時使用其特定的子類的對象,創(chuàng)建對象的過程對程序員來說是透明的夏志,只需要使用getInstance
方法創(chuàng)建即可乃坤。
///默認(rèn)當(dāng)前日期
Calendar cld = Calendar.getInstance();
///可修改為表示2018年12月15日的日歷對象
/// month : 0 ~ 11
cld.set(2018,11,15);
///將天數(shù)修改為10
cld.set(Calendar.DATE,10);
System.out.printf("%tF%n",cld.getTime());//2018-12-10
// 獲得年份
int year = cld.get(Calendar.YEAR);
// 獲得月份
int month = cld.get(Calendar.MONTH) + 1;
// 獲得日期
int day = cld.get(Calendar.DATE);
System.out.printf("%s:%s:%s%n",year,month,day);
-
GregorianCalendar
GregorianCalendar
是Calendar
類的一個具體實現(xiàn)苛让。Calendar
的getInstance()
方法返回一個默認(rèn)用當(dāng)前的語言環(huán)境和時區(qū)初始化的GregorianCalendar
對象沟蔑。GregorianCalendar
定義了兩個字段:AD
和BC
。這是代表公歷定義的兩個時代狱杰。
GregorianCalendar gcld = new GregorianCalendar();
GregorianCalendar gcld1 = new GregorianCalendar(2019,11,30,23,59,59);
System.out.printf("%tc%n",gcld1.getTime());//周一 12月 30 23:59:59 CST 2019
///其他與`Canlendar`一致
Java正則表達(dá)式
Java
中的正則使用主要包括三個類:Pattern
瘦材、Matcher
、PatternSyntaxException
- Java正則表達(dá)式的語法
詳見:https://www.runoob.com/java/java-regular-expressions.html - Java正則表達(dá)式的使用
///檢索字符串是否包含與正則匹配的子字符串
String content = "wowaattterww";
///.* regex .* 用來查找字符串中是否包含被`regex`匹配到的字串
String regex = ".*wa{1,2}t{1,3}er.*"; //它匹配 waater/waatter/waattter等
boolean match = Pattern.matches(regex,content);
System.out.println(match);///true
- 捕獲組
捕獲組是把多個字符當(dāng)一個單獨單元進(jìn)行處理的方法仿畸,它通過對括號內(nèi)的字符分組來創(chuàng)建食棕。例如,正則表達(dá)式 (dog) 創(chuàng)建了單一分組错沽,組里包含"d"簿晓,"o",和"g"千埃。
捕獲組是通過從左至右計算其開括號來編號憔儿。例如,在表達(dá)式:"((A)(B(C)))"
放可,有四個這樣的組:((A)(B(C))))
谒臼、(A)
、(B(C))
耀里、(C)
String content = "wowaattterww888.com";
///分4組,以左括號劃界
/// 0 組 以`reg_p`為整體
// 1 組 只匹配`(\D*)`: 匹配非數(shù)字字符 0個或多個 與反向范圍字符[^0-9]等效
// 2 組 只匹配 `(\d+)`: 匹配數(shù)字字符 1個或多個 與范圍字符[0-9]等效
// 3 組 只匹配 `(.*)` : 匹配單個字符 0個或多個
String reg_p = "(\\D*)(\\d+)(.*)";
Pattern pattern = Pattern.compile(reg_p);
///只能通此來創(chuàng)建`Matcher`類
Matcher matcher = pattern.matcher(content);
//按照慣例蜈缤,第0組表示整個模式。它不包括在此計數(shù)中冯挎。
System.out.println("該正則有"+ (matcher.groupCount() + 1) + "個分組\n");//該正則有4個分組
//Attempts to find the next subsequence of the input sequence that matches the pattern.
boolean found = matcher.find();///匹配到了
if (found) {
System.out.printf("第一個捕獲組的匹配到的值:%s 開始索引:%d,結(jié)束索引:%d%n",matcher.group(0),matcher.start(0),matcher.end(0));//wowaattterww888.com
System.out.printf("第二個捕獲組的匹配到的值:%s 開始索引:%d,結(jié)束索引:%d%n",matcher.group(1),matcher.start(1),matcher.end(1));//wowaattterww888.com
System.out.printf("第三個捕獲組的匹配到的值:%s 開始索引:%d,結(jié)束索引:%d%n",matcher.group(2),matcher.start(2),matcher.end(2));//wowaattterww888.com
System.out.printf("第四個捕獲組的匹配到的值:%s 開始索引:%d,結(jié)束索引:%d%n",matcher.group(3),matcher.start(3),matcher.end(3));//wowaattterww888.com
}
/*
第一個捕獲組的匹配到的值:wowaattterww888.com 開始索引:0,結(jié)束索引:19
第二個捕獲組的匹配到的值:wowaattterww 開始索引:0,結(jié)束索引:12
第三個捕獲組的匹配到的值:888 開始索引:12,結(jié)束索引:15
第四個捕獲組的匹配到的值:.com 開始索引:15,結(jié)束索引:19
*/
-
Matcher
關(guān)鍵方法:lookingAt
與matches
///lookingAt與matches
String content = "waattterwo"; ///
String regex = "wa{1,2}t{1,3}er"; //它匹配 waater/waatter/waattter等
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(content);
///輸出:lookingAt匹配底哥?true matches匹配?false
System.out.println("lookingAt匹配?"+ m.lookingAt() + " matches匹配趾徽?"+ m.matches() + "\n" );
lookingAt
與matches
方法的區(qū)別奶陈,matches
要求整個字符串都要與正則匹配,而lookingAt
不要求附较,但是它要求從字符串的開始位置就要與正則匹配吃粒,否則就是false
。如果將上述代碼:String content = "1waattterwo";
,則lookingAt
會返回false
拒课。
-
Matcher
關(guān)鍵方法:replaceFirst
與replaceAll
replaceFirst
和replaceAll
方法用來替換正則表達(dá)式匹配到的文本徐勃。不同的是,replaceFirst
替換首次匹配早像,replaceAll
替換所有匹配僻肖。
String content = "waa3t2t2t5erwo";
String regex = "\\d+"; //匹配數(shù)字字符 1個或多個
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(content);
String firstReplace = m.replaceFirst("數(shù)字");
String allReplace = m.replaceAll("數(shù)字");
///輸出:replaceFirst:waa數(shù)字t2t2t5erwo replaceAll:waa數(shù)字t數(shù)字t數(shù)字t數(shù)字erwo
System.out.printf("replaceFirst:%s replaceAll:%s%n",firstReplace,allReplace);
-
Matcher
關(guān)鍵方法:appendReplacement
與appendTail
Matcher
類也提供了appendReplacement
和appendTail
方法用于文本替換:
String content = "waa3t2t2t5erwo";
String regex = "\\d+"; //匹配數(shù)字字符 1個或多個
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(content);
StringBuilder sb = new StringBuilder();
while (m.find()) {
m.appendReplacement(sb,"數(shù)字");
}
System.out.println(sb.toString());//waa數(shù)字t數(shù)字t數(shù)字t數(shù)字
m.appendTail(sb);
System.out.println(sb.toString());//waa數(shù)字t數(shù)字t數(shù)字t數(shù)字erwo
Java中的方法
大多與其他語言一致,區(qū)別如下:
- 構(gòu)造方法
構(gòu)造方法和它所在類的名字相同卢鹦,但構(gòu)造方法沒有返回值臀脏。
Java
自動為所有的類提供了一個默認(rèn)構(gòu)造方法,默認(rèn)構(gòu)造方法的訪問修飾符和類的訪問修飾符相同(類為 public
冀自,構(gòu)造函數(shù)也為 public
揉稚;類改為 protected
,構(gòu)造函數(shù)也改為 protected
)熬粗。一旦定義自己的構(gòu)造方法搀玖,默認(rèn)構(gòu)造方法就會失效。
// 一個簡單的構(gòu)造函數(shù)
class MyClass {
int x;
// 以下是構(gòu)造函數(shù)
MyClass(int i ) {
x = i;
}
MyClass() {
x = 10;
}
}
- 可變參數(shù)
格式:typeName... parameterName
可當(dāng)做數(shù)組用
finalize() 方法
Java 9
該方法被棄用了驻呐。
Java
允許定義這樣的方法灌诅,它在對象被垃圾收集器析構(gòu)(回收)之前調(diào)用,這個方法叫做finalize( )
含末,它用來清除回收對象猜拾。
///` finalize( )`方法的一般格式
protected void finalize()
{
// 在這里終結(jié)代碼
}
關(guān)鍵字 protected
是一個限定符,它確保finalize()
方法不會被該類以外的代碼調(diào)用佣盒。
Java中的Stream挎袜、File、IO
Stream
可以理解為一個數(shù)據(jù)的序列沼撕。輸入流表示從一個源讀取數(shù)據(jù)宋雏,輸出流表示向一個目標(biāo)寫數(shù)據(jù)。
- 控制臺輸入與輸出
///接收控制臺輸入的輸入流
InputStreamReader reader = new InputStreamReader(System.in);
char c;
do {
c = (char) reader.read(); ///控制臺輸入完成后务豺,讀取控制臺輸入的字符磨总,one by one
///輸入 wwwwwwqq 輸出 wwwwwwq
System.out.println(c);
} while ( c != 'q');
///轉(zhuǎn)一下,獲取字符流笼沥,讀取整行
BufferedReader bufferedReader = new BufferedReader(reader);
String readStr = bufferedReader.readLine();
System.out.println(readStr);
- 文件讀寫
創(chuàng)建一個文件寫入數(shù)據(jù)蚪燕,進(jìn)行讀取輸出到控制臺娶牌,然后刪除該文件。
///創(chuàng)建輸出流馆纳,寫入項目根目錄
File dir = new File("./test/tmp/");
dir.mkdirs();//會創(chuàng)建中間目錄
///文件不存在诗良,寫入過程中會自動創(chuàng)建
File file = new File("./test/tmp/test.text");
try {
///此類寫入的是字節(jié)流
FileOutputStream fileOutputStream = new FileOutputStream(file);
///包裝一層寫入 編碼后的字符串
OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream,"utf-8");
writer.write("你好,");
writer.append("我是鮑勃\n");
///關(guān)閉寫入流
writer.close();
///關(guān)閉輸出流
fileOutputStream.close();
///讀取文件的內(nèi)容
FileInputStream fileInputStream = new FileInputStream("./test/tmp/test.text");
///讀取解碼后的解碼字符串
InputStreamReader reader = new InputStreamReader(fileInputStream,"utf-8");
///讀取方式1;
///ready 文件不空 返回
StringBuilder sb = new StringBuilder();
while (reader.ready()){
sb.append((char) reader.read());
};
System.out.println(sb.toString());
///讀取方式2:
///返回文件預(yù)估長度鲁驶,字節(jié)數(shù)
///int charLength = fileInputStream.available() / 2;
///char[] chars = new char[charLength];
///charLength = reader.read(chars); ///返回讀到的字符數(shù)
///String res = new String(chars,0,charLength);
///System.out.println(res);
///關(guān)閉讀取流
reader.close();;
///關(guān)閉輸入流
fileInputStream.close();
///刪除文件
System.out.println(file.delete());
///刪除目錄 tmp
dir.delete();
///刪除父級目錄 test
dir.getParentFile().delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Java中的Scanner類
Java 5
新特性鉴裹, 它也可以獲取輸入數(shù)據(jù)。
///文件輸出
File file = new File("./test/tmp/test.text");
Scanner scanner = new Scanner(file);
///皆可
while (scanner.hasNext()) {
System.out.println(scanner.next());///無法獲取空格
}
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());///可以獲取空格
}
scanner.close();
///獲取用戶鍵盤輸入钥弯,進(jìn)行控制臺輸出
Scanner scanner1 = new Scanner(System.in);
while (scanner1.hasNext()) {
System.out.println(scanner1.next());
}
scanner1.close();
Java中異常
與其他語言径荔,差別不大,具體細(xì)節(jié):https://www.runoob.com/java/java-exceptions.html
Java中的繼承
與其他語言差別不大脆霎,關(guān)鍵字extends
总处、implements
、final
- 構(gòu)造方法
子類是不繼承父類的構(gòu)造函數(shù)的睛蛛。
如果父類的構(gòu)造器帶有參數(shù)鹦马,則必須在子類的構(gòu)造器中顯式地通過super
關(guān)鍵字調(diào)用父類的構(gòu)造器并配以適當(dāng)?shù)膮?shù)列表。
如果父類構(gòu)造器沒有參數(shù)忆肾,則在子類的構(gòu)造器中不需要使用super
關(guān)鍵字調(diào)用父類構(gòu)造器荸频,系統(tǒng)會自動調(diào)用父類的無參構(gòu)造器。
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
// SubClass 類繼承
class SubClass extends SuperClass{
private int n;
SubClass(){ // 自動調(diào)用父類的無參數(shù)構(gòu)造器
System.out.println("SubClass");
}
public SubClass(int n){
super(300); // 調(diào)用父類中帶有參數(shù)的構(gòu)造器
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
// SubClass2 類繼承
class SubClass2 extends SuperClass{
private int n;
SubClass2(){
super(300); // 調(diào)用父類中帶有參數(shù)的構(gòu)造器
System.out.println("SubClass2");
}
public SubClass2(int n){ // 自動調(diào)用父類的無參數(shù)構(gòu)造器
System.out.println("SubClass2(int n):"+n);
this.n = n;
}
}
- implements
使用implements
關(guān)鍵字可以變相的使java
具有多繼承的特性难菌,使用范圍為類繼承接口的情況试溯,可以同時繼承多個接口(接口跟接口之間采用逗號分隔)。
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
- final
final 關(guān)鍵字聲明類可以把類定義為不能繼承的郊酒,即最終類;或者用于修飾方法键袱,該方法不能被子類重寫燎窘。
Java的重寫(Override)與重載(Overload)
- 重寫(Override)
重寫是子類對父類的允許訪問的方法的實現(xiàn)過程進(jìn)行重新編寫, 返回值和形參都不能改變。即外殼不變蹄咖,核心重寫褐健!
重寫的規(guī)則:
1.返回類型為被重寫方法的返回類型及其子類。
2.訪問權(quán)限不能比父類中被重寫的方法的訪問權(quán)限更低澜汤。
3.聲明為 static 的方法不能被重寫蚜迅,但是能夠被再次聲明。
4.構(gòu)造方法不能被重寫俊抵。
5.重寫的方法能夠拋出任何非強制異常谁不,無論被重寫的方法是否拋出異常。但是徽诲,重寫的方法不能拋出新的強制性異常刹帕,或者比被重寫方法聲明的更廣泛的強制性異常吵血,反之則可以。 - 重載(Overload)
在一個類里面偷溺,方法名字相同蹋辅,而參數(shù)不同。返回類型可以相同也可以不同挫掏。
每個重載的方法(或者構(gòu)造函數(shù))都必須有一個獨一無二的參數(shù)類型列表侦另。
最常用的地方就是構(gòu)造器的重載。
Java多態(tài)
三要素繼承尉共、重寫淋肾、父類指針指向子類。與其他語言一樣爸邢。
Java抽象類&抽象方法
關(guān)鍵字abstract
樊卓。
規(guī)則:
1.抽象類,不能被實例化杠河;
2.抽象類可以沒有抽象方法碌尔,但有抽象方法的類必定要是抽象類
3.抽象類中定義的抽象方法,必須要被子類 重寫券敌,除非子類也是抽象類
4.構(gòu)造函數(shù)唾戚、Static
修飾的函數(shù),不能為抽象方法待诅。
5.抽象方法只包含一個方法名叹坦,而沒有方法體
Java 接口
Java
接口是抽象方法的集合,關(guān)鍵字interface
卑雁;一個類通過繼承接口的方式募书,來繼承接口中的抽象方法。接口和類是不同的概念测蹲。類實現(xiàn)接口莹捡,而非繼承接口。
Java
中接口可以用來聲明變量扣甲,可指向空指針篮赢,也可以指向?qū)崿F(xiàn)次接口的實例對象。
實現(xiàn)接口的類必須實現(xiàn)接口的所有方法琉挖,除非該類為抽象類启泣。
接口特性:
1.接口中的每個方法都是隱式抽象;接口在聲明的時候也是隱式抽象的示辈; 隱式指定為public abstract
寥茫。
2.接口中可以有變量,但只能是public static final
修飾的變量顽耳。
-
Java8
中可以定義接口的默認(rèn)方法實現(xiàn)(有方法體)坠敷,關(guān)鍵字default
妙同。 -
Java8
中可以定義static
方法實現(xiàn)。
實現(xiàn)接口的關(guān)鍵字: implements
膝迎,接口實現(xiàn)的規(guī)則:
1.類在實現(xiàn)接口方法時粥帚,無法強制拋出異常;可在接口中或?qū)崿F(xiàn)接口的抽象類中拋出該強制異常限次。
2.一個類可以實現(xiàn)多個接口芒涡。
3.一個接口可以繼承另一個接口。
示例:
public interface Animals {
void behavior();
void eat();
void die();
}
public interface Beasts extends Animals{
///定義接口方法
void run();
///定義默認(rèn)方法實現(xiàn)
default void behavior() {
System.out.printf("%s行為:地上跑%n", Beasts.BEASTS);
}
///定義變量
static final String BEASTS = "走獸";
///定義靜態(tài)方法
static String category() {
return BEASTS + "類";
}
}
//可多繼承卖漫,比如 `public interface Birds extends Animals,Beasts`
public interface Birds extends Animals {
///定義接口方法
void fly();
///默認(rèn)實現(xiàn)`Animals`的方法
default void behavior() {
System.out.printf("%s行為:天上飛%n", BIRDS);
}
///定義變量
static final String BIRDS = "飛禽";
///定義靜態(tài)方法
static String category() {
return BIRDS + "類";
}
}
///飛虎费尽!哇
public class FlyTiger implements Beasts, Birds {
@Override
public void behavior() {
Birds.super.behavior();
Beasts.super.behavior();
System.out.println("飛虎行為怪異\n");
}
@Override
public void eat() {
System.out.println(Beasts.category()+":飛虎吃飯");
System.out.println(Birds.category()+":飛虎吃飯");
}
@Override
public void run() {
System.out.println("飛虎在地");
}
@Override
public void die() {
System.out.println("飛虎在地下");
}
@Override
public void fly() {
System.out.println("飛虎在天");
}
}
///使用
public static void main(String[] args) {
Birds birds = new FlyTiger();
birds.fly();
Beasts beasts = new FlyTiger();
beasts.run();
FlyTiger flyTiger = new FlyTiger();
flyTiger.eat();
flyTiger.behavior();
flyTiger.die();
}
Java 枚舉
- 枚舉聲明
enum Color {
BLUE,
RED,
GREEN
}
- 枚舉使用
enum Color {
BLUE,
RED,
GREEN
}
public class EnumTest {
enum Version {
DEV,
RELEASE,
TRAIL
}
public static void main(String[] args) {
Color color = Color.RED;
Version version = Version.DEV;
System.out.println(version);///DEV
System.out.println(color);///RED
}
}
- 枚舉的內(nèi)部實現(xiàn)
enum Color {
BLUE,
RED,
GREEN
}
///內(nèi)部通過`class`實現(xiàn)
class Color {
public static final Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
}
- 關(guān)鍵方法
for (Version v : Version.values()) {///Version.values() 枚舉的所有值
System.out.println(v);
System.out.println(v.ordinal());//索引
System.out.println(Version.valueOf("DEV"));//取值
}
枚舉跟普通類一樣可以用自己的變量、方法和構(gòu)造函數(shù)羊始,構(gòu)造函數(shù)只能使用 private 訪問修飾符旱幼,所以外部無法調(diào)用。
public class EnumTest {
enum Version {
DEV,
RELEASE,
TRAIL;
private Version(){
System.out.println("Version枚舉構(gòu)造函數(shù)被"+this.name() + "調(diào)用\n");
}
public String getInfo() {
return "版本信息" + this.name();
}
}
public static void main(String[] args) {
Version version = Version.RELEASE;///構(gòu)造函數(shù)被調(diào)用
String info = version.getInfo();///信息打印
System.out.println(info);
}
}
- 枚舉可實現(xiàn)抽象方法
enum Color {
BLUE{
public String getInfo() {
return "藍(lán)色";
}
},
RED{
public String getInfo() {
return "紅色";
}
},
GREEN{
public String getInfo() {
return "綠色";
}
};
public abstract String getInfo();
}
public class EnumTest {
public static void main(String[] args) {
for(Color color : Color.values()) {
System.out.println(color.getInfo());
}
}
}
Java集合框架
Java
集合框架主要包括兩種類型的容器:集合(Collection
)突委、鍵值對(Map
)柏卤。
Collection
接口有3
種子類型List
、Set
和Queue
也是接口匀油。具體可實例化的集合類繼承了實現(xiàn)上述接口的抽象類缘缚。
集合中存儲Java
對象。常用的可實例化的集合類:ArrayList
敌蚜、LinkedList
桥滨、HashSet
。常用的Map
可實例化的類:HashMap
弛车。
ArrayList
ArrayList
類是一個可以動態(tài)修改的數(shù)組齐媒,與普通數(shù)組的區(qū)別就是它是沒有固定大小的限制,我們可以添加或刪除元素帅韧。
- ArrayList的繼承與接口實現(xiàn)關(guān)系
///ArrayList的繼承與接口實現(xiàn)關(guān)系
public interface Collection<E> extends Iterable<E>
public interface List<E> extends Collection<E>
public abstract class AbstractCollection<E> implements Collection<E>
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- ArrayList的關(guān)鍵操作
ArrayList<Integer> arrayList = new ArrayList<>();///創(chuàng)建
arrayList.add(100);///添加對象
arrayList.add(300);
arrayList.add(200);
///小->大排序
arrayList.sort((o1, o2) -> {
return o1.compareTo(o2);
});
Collections.sort(arrayList);///小->大
///修改
arrayList.set(1, 250);
///查詢
arrayList.get(0);
///刪除
arrayList.remove(1);
///刪除所有
arrayList.clear();
///遍歷一
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
///遍歷二
for (Integer i : arrayList) {
System.out.println(i);
}
///遍歷三:可以利用iterator.remove()方法刪除元素
Iterator<Integer> iterator = arrayList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
LinkedList
LinkedList
:鏈表里初,是一種常見的數(shù)據(jù)結(jié)構(gòu),是一種線性表忽舟,但是并不會按線性的順序存儲數(shù)據(jù),而是在每一個節(jié)點里存到下一個節(jié)點的地址淮阐。鏈表可分為單向鏈表和雙向鏈表叮阅。與ArrayList
類似,但LinkedList
的增加和刪除的操作效率更高泣特,而查找和修改的操作效率較低浩姥。
以下情況使用 ArrayList
:
1.頻繁訪問列表中的某一個元素。
2.只需要在列表末尾進(jìn)行添加和刪除元素操作状您。
以下情況使用 LinkedList
:
1.需要通過循環(huán)迭代來訪問列表中的某些元素勒叠。
2.需要頻繁的在列表開頭兜挨、中間、末尾等位置進(jìn)行添加和刪除元素操作眯分。
-
LinkedList
的繼承與接口實現(xiàn)關(guān)系
public interface Collection<E> extends Iterable<E>
public interface List<E> extends Collection<E>
public abstract class AbstractCollection<E> implements Collection<E>
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
///多了一層
public abstract class AbstractSequentialList<E> extends AbstractList<E>
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
-
LinkedList
的關(guān)鍵方法
///創(chuàng)建
LinkedList<String> linkedList = new LinkedList<>();
///添加
linkedList.add("java");
linkedList.add("flutter");
linkedList.add("objc");
linkedList.add("swift");
linkedList.add("shell");
///大-> 小 排序
linkedList.sort((o1, o2) -> {
return o2.compareTo(o1);
});
Collections.sort(linkedList);///小->大
///修改
linkedList.set(4,"php");
///刪除
linkedList.remove("php");
//linkedList.remove(3);
///查詢
linkedList.get(0);
///其他
linkedList.addFirst("vue");
linkedList.addLast("js");
linkedList.removeFirst();
linkedList.removeLast();
///遍歷一
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
///遍歷二
for (String str :
linkedList) {
System.out.println(str);
}
///遍歷三: 可以利用iterator.remove()方法刪除元素
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
HashSet
HashSet
無序的拌汇,不允許有重復(fù)元素的集合,它不是線程安全的弊决。如果多個線程嘗試同時修改HashSet
噪舀,則最終結(jié)果是不確定的。 必須在多線程訪問時顯式同步對 HashSet
的并發(fā)訪問飘诗。
-
HashSet
的繼承與接口實現(xiàn)關(guān)系
public interface Collection<E> extends Iterable<E>
public interface Set<E> extends Collection<E>
public abstract class AbstractCollection<E> implements Collection<E>
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
-
HashSet
關(guān)鍵方法
///創(chuàng)建
HashSet<String> hashSet = new HashSet<>();
///添加
hashSet.add(null);//可添加null
hashSet.add("張飛");
hashSet.add("關(guān)羽");
hashSet.add("劉備");
hashSet.add("趙云");
hashSet.add("趙云");//無法添加重復(fù)元素
///刪除
hashSet.remove("趙云");
///刪除所有
hashSet.clear();
///包含
if (hashSet.contains("劉備")) {
System.out.println("包含");
}
///遍歷
for (Object obj: hashSet) {
System.out.println(obj);
}
HashMap
HashMap
是一個散列表与倡,它存儲的內(nèi)容是鍵值對(key-value
)映射。
HashMap
實現(xiàn)了 Map
接口昆稿,根據(jù)鍵的 HashCode
值存儲數(shù)據(jù)纺座,具有很快的訪問速度,最多允許一條記錄的鍵為null
溉潭,不支持線程同步净响。
HashMap
是無序的,即不會記錄插入的順序岛抄。
HashMap
的 key
與 value
類型可以相同也可以不同别惦,可以是字符串(String
)類型的 key
和 value
,也可以是整型(Integer
)的 key
和字符串(String
)類型的 value
夫椭。
-
HashMap
的繼承與接口實現(xiàn)關(guān)系
public interface Map<K, V>
public abstract class AbstractMap<K,V> implements Map<K,V>
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
-
HashMap
的關(guān)鍵方法
///創(chuàng)建
HashMap<Integer,String> map = new HashMap<Integer,String>();
///添加
map.put(1,"1");
map.put(2,"2");
map.put(3,"3");
///如果沒有則添加
map.putIfAbsent(2,"4");
///修改
map.replace(2,"20");
map.put(2,"22");
///刪除
map.remove(3);
//獲取
map.get(2);///22
System.out.println(map);
///遍歷一
for (Integer key : map.keySet()) {
System.out.println(map.get(key));
}
///遍歷二
for (String value:map.values()) {
System.out.println(value);
}
///遍歷三
Iterator<Map.Entry<Integer,String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().getValue());
}
///遍歷四
ArrayList arrayList = new ArrayList<>(map.values());
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
Java中的Object
Java
中Object
類是所有類的父類掸掸,也就是說 Java
的所有類都繼承了 Object
,子類可以使用 Object
的所有方法蹭秋。
Object
類可以顯示繼承扰付,也可以隱式繼承,以下兩種方式時一樣的:
///顯式繼承
pulic class Test extends Object {
}
///隱式繼承
public class test {
}
Java中的泛型
泛型方法
定義泛型方法的規(guī)則:
1.泛型方法需要聲明類型參數(shù)仁讨,類型參數(shù)聲明在函數(shù)返回值類型的前面羽莺,采用尖括號< >
包裹。形如:<E>
2.類型參數(shù)聲明可有多個洞豁,尖括號內(nèi)盐固,彼此用逗號,
隔開
3.類型參數(shù)能被用來聲明返回值類型,并且能作為泛型方法得到的實際參數(shù)類型的占位符丈挟。
4.泛型方法體的聲明和其他方法一樣刁卜。
5.注意類型參數(shù)只能代表引用型類型,不能是原始類型(像 int曙咽、double蛔趴、char 等)。
///示例
public static <T,S> T genericsFunc(T param1, S param2) {
System.out.println(param2);
return param1;
}
泛型類
類名后面添加了類型參數(shù)聲明部分例朱,類型參數(shù)聲明部分也包含一個或多個類型參數(shù)孝情,參數(shù)間用逗號隔開鱼蝉。
public class GenericTest<T,U> {
T type;
U user;
public GenericTest(T type, U user){
this.type = type;
this.user = user;
}
public T getType(){
return this.type;
}
public U getUser(){
return this.user;
}
public void setType(T type) {
this.type = type;
}
public void setUser(U user) {
this.user = user;
}
public static void main(String[] args) {
GenericTest<String,String> genericTest = new GenericTest<>("工人","張三");
genericTest.setType("農(nóng)民");
System.out.println(genericTest.type);
System.out.println(genericTest.user);
}
}
類型通配符與條件限定
類型通配符一般是使用 ?
代替具體的類型參數(shù)。例如 List<?>
在邏輯上是 List<String>,List<Integer>
等所有 List<具體類型實參>
的父類箫荡。不需要額外聲明的類型參數(shù)魁亦。
public static void printArray(List<?> arr) {
System.out.println(arr.get(0));
}
public static void main(String[] args) {
ArrayList list<String> = new ArrayList<String>();
list.add("hello");
printArray(list);
}
- 限定通配符的類型為特定類型的子類:
<? extends T>
public static void printArray(List<? extends Number> arr) {
System.out.println(arr.get(0));
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("hello");
//printArray(list);//報錯
ArrayList<Integer> numlist = new ArrayList<Integer>();
numlist.add(100);
printArray(numlist);
}
- 限定通配符的類型為特定類型的父類:
<? super T>
public static void printArray(List<? super Integer> arr) {
System.out.println(arr.get(0));
}
Java序列化
Java
序列化,是將一個Java
類對象序列化為字節(jié)序列的過程菲茬,該字節(jié)序列會保存對象的數(shù)據(jù)吉挣,也會保存對象類型關(guān)聯(lián)的所有類型的信息;因此該字節(jié)序列也可以通過反序列化轉(zhuǎn)化為對象婉弹。整個過程基于JVM
睬魂,因此該字節(jié)序列支持平臺遷移。
Java
的對象支持序列化的條件镀赌,該對象所屬類型必須實現(xiàn)接口java.io.Serializable
Java
序列化機制的主要類ObjectOutputStream
與ObjectInputStream
氯哮。
- 序列化
當(dāng)序列化一個對象到文件時, 按照Java
的標(biāo)準(zhǔn)約定是給文件一個.ser
擴展名商佛。
public class SerializableTest implements java.io.Serializable {
public String name;
public String job;
public int age;
public boolean hasJob;
public transient String intro; ///無法被序列化
}
public static void serialization() {
///創(chuàng)建對象
SerializableTest testObjc = new SerializableTest();
testObjc.name = "波波";
testObjc.job = "售貨員";
testObjc.age = 20;
testObjc.hasJob = true;
testObjc.intro = "還歲月以文明";
try {
FileOutputStream fileOutputStream = new FileOutputStream("/tmp/test.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
///對象序列化
objectOutputStream.writeObject(testObjc);
fileOutputStream.close();
objectOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
- 反序列化
public static SerializableTest deserialization() {
SerializableTest test = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("/tmp/test.ser");
ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
///反序列化
test = (SerializableTest) inputStream.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return test;
}
public static void main(String[] args) {
serialization();
SerializableTest obj = deserialization();
if (obj != null) {
System.out.println(obj.name);//波波
System.out.println(obj.job);//售貨員
System.out.println(obj.age);//20
System.out.println(obj.hasJob);//true
System.out.println(obj.intro); ///null
}
}
Java多線程
線程狀態(tài)
創(chuàng)建->就緒(進(jìn)入就緒隊列喉钢,待JVM調(diào)度)->運行(獲取CPU資源)->死亡;
運行狀態(tài)下良姆,線程可能因為調(diào)用sleep
肠虽、wait
、suspend
進(jìn)入阻塞狀態(tài)玛追。當(dāng)睡眠時間到或重獲CPU資源便會進(jìn)入就緒狀態(tài)税课。主要有三種阻塞:
1.線程運行時調(diào)用wait
方法進(jìn)入等待阻塞。
2.同步阻塞痊剖,同步鎖:synchronized
韩玩。
3.其他阻塞,如:sleep
陆馁、join
(等待線程終止或超時或I/O處理完畢)找颓。
線程優(yōu)先級
Java
中線程的優(yōu)先級0~10
,如果不設(shè)置優(yōu)先級默認(rèn)為5
叮贩。
線程創(chuàng)建
- 通過實現(xiàn)
Runnable
接口創(chuàng)建線程
創(chuàng)建一個實現(xiàn)Runnable
接口的類击狮,該類需創(chuàng)建一個Thread
實例,運行該Thread
實例的start()
方法益老,讓線程執(zhí)行帘不。
一個實現(xiàn)了Runnable
的類可以通過實例化一個Thread
實例并將自己作為目標(biāo)傳入,從而在不子類化Thread
的情況下運行杨箭。在大多數(shù)情況下,如果你只打算覆蓋run()
方法而不覆蓋其他的Thread
方法储狭,那么就應(yīng)該使用Runnable
接口互婿。
public class ThreadTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());///main
startNewThread("線程1");
}
public static void startNewThread(String threadName) {
///創(chuàng)建一個實現(xiàn)`Runnable`接口的類
Runnable runnable = new Runnable() {
///實現(xiàn)`run`方法
///獲取CPU資源運行任務(wù)
@Override
public void run() {
System.out.println(Thread.currentThread().getName());///線程1
try {
///阻塞 5s
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName +"休眠結(jié)束");///線程1休眠結(jié)束
}
};
///創(chuàng)建線程
Thread t = new Thread(runnable,threadName);
///就緒捣郊,加入線程隊列,
t.start();
}
}
- 通過繼承
Thread
來創(chuàng)建線程
public class ThreadTest extends Thread {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());///main
ThreadTest customThread = new ThreadTest("線程1");//線程1
customThread.start();
}
public ThreadTest(String name) {
super(name);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName());///線程1
try {
///阻塞 5s
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName() +"休眠結(jié)束");///線程1休眠結(jié)束
}
}
- 通過
Callable
和Future
創(chuàng)建線程
public class ThreadTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());///main
///創(chuàng)建一個實現(xiàn)`Callable`接口的類
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 100;
}
};
///使用`FutureTask`包裝
FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
//創(chuàng)建線程慈参,并將`FutureTask`作為線程執(zhí)行對象
Thread thread = new Thread(futureTask);
///使線程處于就緒狀態(tài)
thread.start();
try {
///取值
Integer integer = futureTask.get();
System.out.println(integer);///100
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}