前言
之前基本確定之後的求職方向,但一直學習沒有方向沒有系統的路線,放假期間捋了一下自己的思路,感覺確確實實知識得系統的學,尤其基礎的應用最多的技術知識。
Java是本科選修過,但是當時只是單純考試考完基本上就是平常有項目的時候會用到,沒有很系統的知識體系。既然以後大機率是往後端開發去靠近,那完全是有必要把基礎夯實,構建完整的知識體系,所以也就利用時間過了一遍JavaSE基礎,在此進行簡單的記錄總結。
Java基礎(不定時更新)
- Java定義
Java語言是Sun公司在1995年推出的高級編程語言,可使用編程語言對計算機下達命令讓計算機完成人們需要的功能
Java平臺 由Java虛擬機(JVM)和Java應用編程接口構成 - Java特點
- 面向對象,只支持類間的單繼承,可通過接口實現多繼承
- 平臺無關性,“一次編寫,到處運行”,Java程序經過解釋後生成.class字節碼文件,字節碼文件在JVM中運行(不同操作系統適配不同的JVM),只要系統中有JVM即可運行Java程序
- 簡單性,Java語言中無指針,並且有垃圾回收機制解決程序員需管理內存的問
- 解釋執行,Java編譯器將Java程序編譯成字節碼文件,通過解釋器對字節碼文件解釋執行
- 多線程,Java支持多個線程通過執行,執行的方法寫在線程的run方法體中
- . 分佈式,Java支持Internet應用的開發,提供網絡應用編程的類庫,包括URL、URLConnection、Socket等
- 安全性、健壯性、高性能等
- JavaSE、JavaEE、JavaME
JavaSE:Java Standard Edition,Java標準版,可視爲JavaEE的子類,允許開發和部署在桌面、服務器、嵌入式環境和實施環境中使用的Java應用程序
JavaEE:Java Enterprise Edtion,Java企業版,多用於企業級開發,包括Web開發等
JavaME:Java Platform Micro Edition,Java平臺微型版,爲在移動設備和嵌入式設備(例如手機、電視機頂盒、打印機)上運行的應用程序提供一個健壯靈活的環境 - JVM
Java可可跨平臺是由於JVM運行環境的支持,不同操作系統中提供不同的JVM對Java程序起翻譯作用(Java虛擬機JVM本身不具備跨平臺功能,每個操作系統下都有不同版本的虛擬機促使Java具有跨平臺特性) - Java內存
Java內存分爲棧、堆、方法區、本地方法棧、寄存器五部分。- Stack棧:存放方法中的局部變量,方法的運行需要在棧中進行
- Heap堆:new的實例化對象在堆中,堆中存儲的是對象的地址值,數據均由默認值(整數0、浮點數0.0、字符\u0000、布爾false、引用類型null)
- Method Area方法區:存儲.class相關信息(包括方法信息)
- Native Method Stack本地方法棧:與操作系統有關
- PC Register寄存器:與CPU有關
- JRE、JDK
JRE:Java Runtime Environment:Java程序的運行時環境,包含JVM和運行時所需要的核心類庫
JDK:Java Development Kit,Java程序開發工具包,包含JRE和開發人員使用的工具
如果單純運行一個已有的Java程序則只需安裝JRE即可;如果需要開發一個新Java程序,必須安裝JDK - Java編程規範
- 關鍵字
關鍵字不可作爲一般的標識符來使用。 - 標識符
標識符爲程序員自定義的內容,如類名稱、方法名字、變量名字等。
標識符可包含英文字母(區分大小寫)、0-9數字、$(美元符號,最好不使用,Java中內部類.class中包含此符號)和_(下劃線),但是不能以數字開頭
類名規範:大駝峯,所有的單詞首字母均大寫
變量名/方法名規範:小駝峯,首字母小寫,後面每個單詞首字母大寫 - 常量
程序運行期間,固定不變的量。- 字符串常量:“abc”
- 整數常量:3
- 浮點數常量:2.5
- 字符常量:‘A’
- 布爾常量:true、false
- 空常量:null,代表沒有任何數據
- 變量
變量即程序運行期間內容可發生改變的量。
//1. 變量創建方式1:
//數據類型 變量名稱;
//變量名稱= 數據值;
int a;
a = 2;
//2. 變量創建方式2:
//數據類型 變量名稱 = 數據值,將=右邊的數據值賦給=左邊的變量
int b = 2;
變量必須賦值後才能使用,否則編譯時會報錯。作用域在定義變量始,至直接所屬大括號結束爲止
- 數據類型
數據類型分爲基本數據類型和引用數據類型。
基本數據類型 | |
---|---|
整數型 | byte(1個字節) short(2個字節) int(4個字節) long(8個字節,使用long需要加上後綴L) |
浮點型 | float(4個字節) double(8個字節浮點型中默認爲double,使用float需要加上後綴F) |
字符型 | char(2個字節) |
布爾型 | boolean(1個字節) |
引用數據類型 |
---|
字符串 |
數組 |
類 |
接口 |
Lambda |
13. 數據類型轉換
當數據類型不一樣時會發生類型轉換。數據類型轉換分爲顯式轉換和隱式轉換。
1. 顯式數據類型轉換/強制類型轉換:一般是大轉小(可能存在數據丟失)
int num = (int)100L;//將8字節的long類型強制類型轉換爲4字節的int類型
2. 隱式數據類型轉換/自動類型轉換:一般是小轉大,不需特殊處理系統自動完成。
double f= 2.15F;//float類型隱式類型轉換爲doubel(4字節轉爲8字節)
- 運算符
運算符 | 具體描述 |
---|---|
算術運算符 | + - * / %(取餘)【一旦運算中有不同類型的數據,結果同數據類型範圍大的類型;char:先轉int再運算;String:+字符串拼接】 |
賦值運算符 | += -= *= /= %= |
比較運算符 | == < > <= >= !=(結果爲boolean值) |
邏輯運算符 | && ! 或 |
三元運算符 | 數據類型 變量名稱 = 條件判斷 ? 表達式A : 表達式B |
- 語句
順序語句:按照程序編寫順序依次執行
選擇語句:if if-else if-elseif-else swtich(小括號裏可爲byte short char int String enum) break continue
循環語句:fori(正序) forr(倒序) do-while while - 方法
方法即將某個功能抽取出來的一個封裝,需要使用此功能的時候調用方法即可,實現代碼的複用性且解決代碼冗餘現象。
修飾符 返回值類型 方法名 (參數列表){
......//方法體
return 返回值
}//方法定義無先後順序
- 方法重載與方法重寫
方法重載:overwrite,參數列表不同(個數、類型、順序不同),其他方法返回值類型、方法名稱相同(只需記住一個方法名稱通過傳入不同的參數調用不同的方法實現類似的多個功能)
方法重寫:override,子類繼承重寫父類的方法,實現類重寫接口的方法(返回值可不同,需要小於等於父類方法的返回值,修飾符的作用域需要大於等於父類方法的修飾符) - 數組
- 數組是一個容器可同時存放多個數據值
- 引用數據類型
- 存放的數據類型必須統一
- 數組長度在程序運行期間不可改變。
數組的初始化分爲靜態初始化(指定內容)和動態初始化(指定長度)
//1.1 數組的靜態初始化
int[] arr1 = new int[]{1,2,3};
//1.2 數組的靜態初始化(省略new實例化部分)
int[] arr2 = {1,2,3};
//2. 數組的動態初始化
String[] str1 = new String[2];//可存放2個String字符串的數組str1
常見的數組問題:數組索引越界(ArrayIndexOutOfBoundsException);空指針異常(NullPointerException)
19. 類與對象
Java是面向對象的程序編程語言。
面向過程:當需要實現一個功能時需要考慮到每一個具體的步驟,詳細處理每一個細節
面向對象:當需要實現一個功能時,不關心具體步驟,找一個已有該功能的方法來調用即可
類:一組相關屬性(成員變量)和行爲(成員方法)的集合,用來描述一類事物,屬性即事物的狀態信息,行爲即事物可以做的事
20. 封裝
面嚮對象語言的特徵之一。封裝就是將一些細節信息隱藏起來對於外界不可見。
方法是一種封裝,private是一種封裝。
21. 繼承
子類 extends 父類
22. super和this
構造方法中super和this不可同時使用
23. 多態
多態是針對於一個對象而言的,表示這個對象有多個形態(extends繼承/implements實現是多態的前提)
//對象的向下轉型(隱式轉型)
父類 父類對象名 = new 子類();
//使用instanceof進行類型判斷
if(對象名 instanceof 子類名){
子類 子類對象名 = (子類名)對象名;//對象的向上轉型(強制轉型)
}
- 接口
public interface 接口名稱{
......//抽象方法
public abstract 返回值類型 方法名稱(參數列表);//public abstract可省略
}
25. 異常
異常是指程序在執行過程中出現的非正常情況,最終會導致JVM的非正常停止。
Java中異常本身就是一個類,產生異常就是創建異常對象並拋出一個異常對象,在Java中處理異常的方式是中斷處理。
異常分爲error、exception。
error是不可恢復不可處理的(例如內存溢出等),應該儘量避免
exception分爲編譯期異常和運行時異常,對於編譯期異常需要自定義捕獲異常處理異常,對於運行時異常(空指針、數組邊界溢出)程序會自動拋出異常,無需處理。
異常處理:throw new XXXException/方法外加throws XXXException/try-catch(try中創建異常捕獲異常,catch中異常處理)
if進行異常捕獲,throw進行異常拋出;如果throw拋出的是RuntimeException,那麼直接交予JVM處理,可throw new XXXException創建異常對象的時候傳入自定義打印的message參數,JVM打印異常信息(內容message、原因XXXException、位置);如果throw拋出的是編譯期異常對象,那麼一般要麼在方法名throws XXXException捕獲異常聲明性輸出異常(終止程序),要麼加try-catch捕獲異常處理異常(catch異常處理後程序繼續執行);如果使用進行try-catch異常捕獲和處理直接將可能出現異常的語句或者throw new XXXException創建異常對象語句放入到try中,然後catch進行異常分類定義處理即可(try捕獲到異常後創建異常對象並拋出直接挨個遍歷catch找到匹配的處理方法,catch接收到try拋出的異常通過其中的方法處理異常即可);如果方法中有異常處理,那麼需要注意調用有異常方法的方法也需要進行異常處理,throws或者try-catch
- 集合
集合是Java提供的一種容器用來存儲多個數據。與數組相比長度可變,且數據類型爲包裝類
- 併發
- Lambda表達式
- Properties類
//store將Properties屬性集內容讀取到文件中
//1. 定義Properties對象
Properties properties = new Properties();
properties.setProperty("key1","value1");
properties.setProperty("key2","value2");
properties.setProperty("key3","value3");
//2. 定義輸出流對象,可字節流可字符流
FileWriter fileWriter = new FileWriter("C:\\Users\\cici\\test.txt",false);
//3. 調用Properties對象的store方法將屬性集key-value寫入文件中 第二個參數爲註釋,可爲""空字符串
properties.store(fileWriter,"");
//4. 關閉輸出流
fileWriter.close();
//load將文件中的內容加載到Properties屬性集中
//1. 定義Properties對象
Properties properties = new Properties();
//2. 定義輸入流對象,可字節流可字符流(如果有中文最好是字符流)
FileReader fileReader = new FileReader("C:\\Users\\cici\\test.txt");
//3. 調用Properties對象的load方法將文件中的數據讀取到Properties屬性集中
properties.load(fileReader);//文件中的註釋內容不會被讀入
//4. 遍歷讀取屬性集的內容
for(String key : properties.stringPropertyNames()){
System.out.println(key + " = " + properties.getProperty(key));
//key3 = value3
//key2 = value2
//key1 = value1
}
//4. 關閉輸入流資源
fileReader.close();
- IO流
//字節輸入流
//1. 使用FileInputStream的構造方法,參數爲File路徑名(絕對路徑/相對路徑都可)
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\cici\\test.txt");
int len =0;
byte[] bytes = new byte[2];
//2 加while循環讀取File
while((len = fileInputStream.read(bytes))!=-1){
System.out.println(new String(bytes));
}
//3. 使用結束關閉FileInputStream,釋放資源
fileInputStream.close();
//字節輸出流
//1. FileOutputStream構造方法,參數爲String類型的文件名/File類型的文件
//將FileOutputStream對象綁定到File文件對象上(File若不存在則創建)
//FileOutputStream的構造方法加參數append=true,表示追加;false表示創建一個新文件覆蓋原文件
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\cici\\test.txt",false);
//2 數據換行
byte[] bytes = "你好\r\ncici\r\n".getBytes();
fileOutputStream.write(bytes);
//3. close方法關閉輸出流,釋放資源
fileOutputStream.close();//替代flush方法
//字符輸入流
//1. 定義FileReader對象,並指定文件路徑
FileReader fileReader = new FileReader("C:\\Users\\cici\\test.txt");
//2. 調用FileReader的read方法讀取
//2.1 讀取依次一個字節
int len =0;
// while((len = fileReader.read())!=-1){
// System.out.println(len);//返回字節
// //65 66 20013 22269 20154
// }
//2.2 讀取字符
char[] chars = new char[1024];
while((len = fileReader.read(chars))!=-1){
System.out.println(new String(chars));//AB中國人
}
//3. 關閉資源
fileReader.close();
//字符輸出流
//1. 定義FileWriter對象,定義FiLe文件,並將FielWriter對象指向File文件,選擇追加模式(append=true)
FileWriter fileWriter = new FileWriter("C:\\Users\\cici\\test.txt",true);
//2. 定義要寫入的char[]數組/String字符串,將字符寫入內存緩衝區進行字符-字節的轉換
//2.1 char[]字符數組
// char[] chars = new char[]{'中','德','關','系','友','好'};
// fileWriter.write(chars);
//2.2 string字符串
fileWriter.write("吧啦啦啦啦啦啦啦啦啦\r\n東方季道啥底料",2,12);
//3. 將內存緩衝區中的字節刷寫到硬盤文件中
// fileWriter.flush();
//4. 關閉資源(同樣可刷寫)
fileWriter.close();
- 緩衝流
//字節緩衝輸入流
//1. 定義文件字節輸入流
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\cici\\test.txt");
//2. 定義輸入字節緩衝流 構造方法中參數可加size去規定緩衝區大小
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
//3. 執行read方法讀取文件
int len=0;
while((len=bufferedInputStream.read())!=-1){
System.out.println(len);
}
//4. 關閉資源,關閉緩衝區即可
bufferedInputStream.close();
//字節緩衝輸出流
//1. 定義文件字節輸出流
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\cici\\test.txt",true);
//2. 定義緩衝字節輸出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//3. 將字節數據寫入緩衝區,參數可byte[]/int
bufferedOutputStream.write("fsfefdfd".getBytes());
//4. 可調用flush方法刷寫
// bufferedOutputStream.flush();
//4. 關閉緩衝區資源(自帶flush)
bufferedOutputStream.close();
//字符緩衝輸入流
//1. 定義字符輸入流
FileReader fileReader = new FileReader("C:\\Users\\cici\\test.txt");
//2. 定義字符緩衝輸入流
BufferedReader bufferedReader = new BufferedReader(fileReader);
//3. 讀取數據
String rrl = null;
//read方法一次讀取一個字符/char[]個字符,讀完返回-1
//readLine方法可換行一次讀取文件中的一行數據,文件讀完返回null
while((rrl = bufferedReader.readLine())!=null){
System.out.println(rrl);
//#
//#Tue Mar 24 21:30:59 CST 2020
//key3=value3
//key2=value2
}
//4. 釋放資源
bufferedReader.close();
//字符緩衝輸出流
//1. 定義字符輸出流
FileWriter fileWriter = new FileWriter("C:\\Users\\cici\\test.txt");
//2. 定義緩衝字符輸出流
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//3. 寫入字符至緩衝區
for(int i=0;i<3;i++){
bufferedWriter.write("fsfsefsg" + i);
//自動換行,相當於不同版本操作系統中的換行符,如Windows下的\r\n
bufferedWriter.newLine();
}
//4. 關閉資源
bufferedWriter.close();//順帶先flush再close(多個寫先在緩衝區中後寫入內存緩衝區,最後flush到硬盤上)
- 轉換流
使用IO流的時候規定字符集的編碼格式,用來解碼和編碼。常用UTF-8,中文用GBK,英文用ASCII,拉丁文用ISO-8859-1,基本上統一使用UTF-8
//1. 定義轉換輸出流,編碼規則爲utf-8
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
new FileOutputStream("C:\\Users\\cici\\test.txt",true),"utf-8");
//2. 定義轉換輸入流,編碼規則爲gbk
InputStreamReader inputStreamReader = new InputStreamReader(
new FileInputStream("C:\\Users\\cici\\test1.txt"),"gbk");
//3. 讀取文件字符
int len = 0;
char[] chars = new char[2];
while((len = inputStreamReader.read(chars))!=-1){
//4. 寫入文件
outputStreamWriter.write(chars);
}
//4. 關閉資源
outputStreamWriter.close();
inputStreamReader.close();
- 序列化流
//1. 定義Person類型的集合
ArrayList<Person> arrayList = new ArrayList<>();
//2. 增加集合元素
Collections.addAll(arrayList, new Person("wangmeimei",19),
new Person("leilei",20),new Person("liming",18));
//3. 定義序列化流對象ObjectOutputStream
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
new FileOutputStream("C:\\Users\\cici\\test.txt",false));
//4. 序列化
objectOutputStream.writeObject(arrayList);
//5. 定義反序列化對象ObjectInputStream
ObjectInputStream objectInputStream = new ObjectInputStream(
new FileInputStream("C:\\Users\\cici\\test.txt"));
//6. 反序列化
ArrayList<Person> arrayList1 = (ArrayList<Person>)objectInputStream.readObject();
//7. 遍歷集合
for(Person person : arrayList1){
System.out.println(person);
//Person{name='wangmeimei', age=19} Person{name='leilei', age=20} Person{name='liming', age=18}
}
//8. 釋放資源
objectOutputStream.close();
objectInputStream.close();
- Socket編程
//client客戶端代碼
public class Demo01Client {
public static void main(String[] args) throws IOException {
//1. 定義Socket,參數爲ip,port
Socket socket = new Socket("localhost",80);
//2. 獲取客戶端字節輸出流
OutputStream out = socket.getOutputStream();
//3. 寫數據到輸出流
out.write("testtesttest".getBytes());
//停止客戶端輸出,如果沒有這一句,服務端inputstream永遠不能退出while(len!=-1),也就無法outputstream回覆給客戶端
socket.shutdownOutput();
//4. 獲取服務端字節輸入流
InputStream in = socket.getInputStream();
//5. 讀取輸入流中的數據
byte[] bytes = new byte[1024];
int len = 0;
while((len = in.read(bytes))!=-1){
System.out.println(new String(bytes));
}
//6. 關閉資源(只用釋放socket即可)
// in.close();
// out.close();
socket.close();
}
}
//server服務端代碼
public class Demo01Server {
public static void main(String[] args) throws IOException {
//1. 定義服務端,參數爲port(同客戶端socket定義的port
ServerSocket serverSocket = new ServerSocket(80);
//2. 使用服務端對象的accept方法綁定客戶端對象,生成一個socket對象與客戶端的socket進行交互
Socket socket = serverSocket.accept();
//3. 定義輸入流使用getInputStream方法接收客戶端的輸出流
InputStream in = socket.getInputStream();
//4. 輸出客戶端發來的數據
byte[] bytes = new byte[1024];
int len=0;
while((len = in.read(bytes))!=-1){
System.out.println(new String(bytes));
}
//5. 定義輸出流發送回覆
OutputStream out = socket.getOutputStream();
out.write("reply".getBytes());
//6. 關閉資源
socket.close();
serverSocket.close();
}
}
- Stream流
String[] strings = {"abc","efd","egty"};
String[] strings1 = {"egd","ethh","wgfd"};
Stream stream = Stream.of(strings);
Stream stream1 = Stream.of(strings1);
long num = stream.skip(1).filter(new Predicate() {
@Override
public boolean test(Object o) {
if(o.equals("efd")){
return true;
}return false;
}
}).count();
System.out.println(num);
stream1.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
- 方法引用
總結
不管怎麼說,學到就是賺到。多學點東西多夯實理論體系基礎多多實踐總結經驗總歸是不會出錯的,既然確定了目標和方向,幹就完事了。