Java名詞
變量、 集合、
源文件:.java文件,存儲Java源代碼的文件
字節碼文件:.class文件,由Java源代碼編譯后生成的.class文件,可以被JVM讀取和執行的文件。
運行Java程序,其實就是執行.class字節碼文件,由JVM把字節碼數據再轉為二進制的機器指令執行。
數據類型
基本數據類型:8種,byte,short,int,long,float,double,char,boolean
引用數據類型:類、接口、枚舉、數組、注解
變量
變量根據數據類型的不同分為基本數據類型的變量和引用數據類型的變量。
變量根據聲明位置不同分為成員變量和局部變量
(A)局部變量聲明位置:
①方法的形參列表
②方法體{}中
③代碼塊{}中
(B)內存存儲的位置不同
局部變量:棧
實例變量:堆
類變量:方法區
(C)生命周期
局部變量
實例變量:每一個對象的成員變量是獨立的,和對象的生命周期一致
類變量:和類的生命周期一致
(D)作用域
局部變量:作用域非常小,從聲明它的位置開始,到它所屬的}結束,可能只屬於某個if,for,方法等
類變量:整個類中
實例變量:整個類中除了靜態方法和靜態代碼塊中不能使用
(E)修飾符
局部變量:唯一可以有的修飾符是final
整數與整數相除,只保留整數部分
取模結果的正負號只看被模數
++/--在后的,就先取值,后自增/自減
擴展賦值運算符+=右邊的計算結果的類型如果比左邊的大的話會強制類型轉換,所以結果可能有風險。
比較表達式的運算結果一定只有true/false
&&它和邏輯與不同的是當&&左邊為false時,右邊就不看了。
||它和邏輯或不同的時當||左邊為true時,右邊就不看了。
條件表達式 ? 結果表達式1 : 結果表達式2 //為true返回1,否則返回2
<< 左移動幾位,右邊補0。左移幾位就是乘以2的幾次方
>> 右移動幾位,左邊補0或1,看最高位。右移幾位就是除以2的幾次方
>>> 右移動幾位,左邊一律補0
按位與:& 運算規則,把兩個數的二進制一一對應,對應位按位與。
按位或:| 運算規則,把兩個數的二進制一一對應,對應位按位或。
按位異或:^ 運算規則,把兩個數的二進制一一對應,對應位按位或。
按位取反:~ 運算規則,把某個數的二進制,按位取反,注意:包括最高位也會取反,這個和從原碼到反碼是不一樣的。
優先級:需要先計算的就用()括起來
對象1 == 對象2 //比較的是地址,而且對象1和對象2的類型要一致或者是父子類關系,否則編譯不通過
對象 instanceof 類型
只有當該對象屬於這個類型才會返回true,而且要求該對象的編譯時類型必須與要判斷的類型一致或有父子類關系
引用數據類型的類型或對象,可以通過 . 來訪問屬性、方法等。
()用於強制類型轉換或優先計算強制類型轉換
流程:解決問題的步驟
(2)分支語句:選擇其中一個分支執行
(3)循環語句:重復執行某些代碼
凡是有[]的都是數組
使用class聲明的類型都是類
【修飾符】 class 類名 【extends 父類】 【implements 父接口n】{
}
類中可以包含5個部分:
(1)成員變量:
靜態成員變量:存儲類共享數據
非靜態成員變量:存儲對象獨立數據
(2)成員方法:完成功能
(3)構造器:創建對象,是實例初始化的一部分
(4)代碼塊:
靜態代碼塊:類初始化的一部分
非靜態代碼塊:實例初始化的一部分
【修飾符】 interface 接口 【extends 父接口們】{
}
接口中的成員有限制要求:
JDK1.8之前:
(1)公共的靜態的常量:public static final
(2)公共的抽象方法:public abstract
JDK1.8之后,增加了:
(3)公共的靜態方法:public static
(1)修飾符:>=父類權限
(2)返回值類型
基本數據類型和void:必須相同
引用數據類型:<=父類類型
(3)方法名:必須相同
(4) 形參列表:必須相同
(5)拋出的異常類型:<=父類類型
【修飾符】 enum 枚舉類型名 【implements 父接口們】{
}
枚舉是一種特殊的類:
(1)枚舉的首行必須是枚舉的常量對象列表;
(2)枚舉的構造器都是private
參數就是一種傳遞數據的方式,所以參數就是一個變量,具有特殊作用的特殊位置的變量。
(1)形參(formal parameter)
在聲明方法時()中的參數
(2)實參(actual parameter)
在調用方法時()中的參數,實參是給形參賦值的,所以實參的個數、類型、順序必須與形參一一對應。
(3)有參(has parameter)
聲明方法時有形參列表,調用方法時有實參列表
(4)無參(no parameter)
聲明方法時沒有形參列表,調用方法時沒有實參列表
(5)命令行參數(command line parameter/ arguments)
運行main時,給main傳的參數
java 類名 命令行參數1 命令行參數2 ....
(6)可變參數(variable parameter)
聲明:
【修飾符】 返回值類型 方法名(【非可變參數部分的形參列表,】 可變參數類型... args)throws 異常列表{
for(int i=0; i<args.length; i++){ //可變參數部分當做數組使用
//...
}
}
(7)類型參數(type parameter,generic Type)
凡是代碼中出現在<>中的類型,就是類型參數。
(8)類型形參(type parameter)
在聲明類/接口時聲明的類型參數,也稱為泛型形參
【修飾符】 class 類名/接口<類型形參列表>{}
【修飾符】 class 類名/接口<類型形參1 extends 父類上限 & 父接口上限>{}
在聲明方法時聲明的類型參數
【修飾符】 <泛型形參列表> 返回值類型 方法名(【數據形參列表】)【throws 異常列表】{}
【修飾符】 <泛型形參 extends 父類上限 & 父接口上限> 返回值類型 方法名(【數據形參列表】)【throws 異常列表】{}
(9)類型實參(type arguments)
在使用泛型類/接口時指定泛型類型的類型參數
在使用泛型方法時傳給泛型類的變量會自動識別變量類型,即為泛型方法實參
(10)傳參(pass parameter)
凡是實參給形參賦值都是叫做傳參。
記住:實參與形參的類型、個數、順序一一對應即可。
使用@interface聲明的類型都是注解,只要使用@標記符的都是注解
@元注解
【修飾符】 @interface 注解名{
數據類型 參數名();
數據類型 參數名() default 默認值;
}
(2)給配置參數賦值的標准格式:參數名 = 參數值,但是如果注解的配置參數只有一個,而且名稱是value,那么在賦值時可以省略value=
(3)如果配置參數是數組類型,那么賦值時可以用“{多個值}”
@Override
用於檢測被修飾的方法為有效的重寫方法,如果不是,則報編譯錯誤!
只能標記在方法上。
- @Test:標記在非靜態的測試方法上。需導入junit包
文檔注解:
-
@author 標明開發該類模塊的作者,多個作者之間使用,分割
-
@version 標明該類模塊的版本
-
@see 參考轉向,也就是相關主題
-
@since 從哪個版本開始增加的
-
@param 對方法中某參數的說明,如果沒有參數就不能寫
-
-
@throws/@exception 對方法可能拋出的異常進行說明 ,如果方法沒有用throws顯式拋出的異常就不能寫
-
其中 @param @return 和 @exception 這三個標記都是只用於方法的。
-
@param的格式要求:@param 形參名 形參類型 形參說明
-
@return 的格式要求:@return 返回值類型 返回值說明
-
@exception 的格式要求:@exception 異常類型 異常說明
-
@param和@exception可以並列多個
-
Java異常和錯誤的根父類:java.lang.Throwable
(1)只有是這個類或它的子類的對象,才能被JVM或throw語句“拋”出
(2)也只有這個類或它的子類的對象,才能被catch給“捕獲”
(3)如果用戶需要自定義異常,那么必須繼承Throwable或它的子類。
Java異常的分類:
- Error:錯誤,合理的應用程序不應該試圖捕獲的異常.
- Exception:異常,合理的應用程序應該、想要捕獲的異常。 Java異常的分類:
- 運行時異常(非受檢異常):RuntimeException及其子類,編譯器不會提示你需要加try...catch處理
try{
}catch(...){
}finally{
//無論try中是否發生異常,也無論catch是否捕獲異常,也不管try和catch中是否有return語句,都一定會執行
}
或
try{
}finally{
//無論try中是否發生異常,也不管try中是否有return語句,都一定會執行
}
語法格式:
try(需要關閉的資源對象的聲明){
業務邏輯代碼
}catch(異常類型 e){
處理異常代碼
....
它沒有finally,也不需要程序員去關閉資源對象,無論是否發生異常,都會關閉資源對象
常見的異常類型
byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
boolean -> Boolean
void -> Void
裝箱:把基本數據類型轉為包裝類對象。
拆箱:把包裝類對象拆為基本數據類型。
在緩存范圍內的對象,緩沖的常量對象在方法區直接引用。沒有緩存的對象,每一個都是新new的
創建多線程的兩種方式(JavaSE階段)
1、 繼承Thread類
(1)編寫線程類,繼承Thread類
(3)創建自定義線程類的對象
(4)調用start()方法啟動線程
2、實現Runnable接口
(1)編寫線程類,實現Runnable接口
(2)必須重寫public void run(){}
(3)創建自定義線程類的對象
(4)通過Thread類的代理對象,調用start()方法啟動線程
如:MyRunnable my = new MyRunnable();
Thread t = new Thread(my);
t.start();
1、什么情況下會有線程安全問題? 多個線程使用了共享數據
2、如何解決線程安全問題? SE階段:synchronized
(1)同步代碼塊
synchronized(鎖對象){
//在一個線程執行期間,不想要被其他線程打擾的代碼,一般是一次事務的原子性操作。
}
鎖對象:自選的,但是要保證使用共享數據的這多個線程必須共用一個鎖對象(監視器對象)
至於是否可以選用this作為鎖對象,要看是否多個線程共用同一個this對象
(2)同步方法
【修飾符】 synchronized 返回值類型 方法名(【形參列表】){
//在一個線程執行期間,不想要被其他線程打擾的代碼,一般是一次事務的原子性操作。
}
鎖對象:固定,非靜態方法就是this,靜態方法就是當前類的Class對象
多線程間的通信就是通過鎖對象調用wait()等待與鎖對象調用notify()喚醒來達到多線程間的調度
集合
集合:是一種容器,用來裝對象的容器,不能裝基本數據類型。也可以說是一種數據結構
Collection
中的集合稱為單列集合,Map
中的集合稱為雙列集合。
元素的通用獲取方式。在取元素之前先要判斷集合中有沒有元素,如果有,就把這個元素取出來,繼續在判斷,如果還有就再取出出來。一直把集合中的所有元素全部取出。
專門操作 List 集合的一些方法
ArrayList、Vector 順序結構,線性的,動態數組的實現
Stock 鏈式結構,先進后出,棧結構
LinkedList 鏈式順序結構,雙端隊列,雙鏈表的實現,既可以用作FILO堆棧使用,又可以用作FIFO隊列使用。
HashSet、底層new的 HashMap
- HashSet 按 Hash 算法來存儲集合中的元素,因此具有很好的存取和查找性能。
- 存儲到HashSet的元素要重寫hashCode和equals方法。
LinkedHashSet 、底層new的 LinkedHashMap
- LinkedHashSet是HashSet的子類,增加兩個屬性before和after維護了結點的前后添加順序
- LinkedHashSet插入性能略低於 HashSet,但在迭代訪問 Set 里的全部元素時有很好的性能。
TreeSet 底層new的TreeMap
Map
- Map中的集合不能包含重復的鍵,值可以重復;每個鍵只能對應一個值
- Map.Entry是Map接口的內部接口,實際上是將Key---->value的數據存儲在Map.Entry接口的實例中,再在Map集合中插入Map.Entry的實例化對象
- 判斷兩個 key 相等的標准是:兩個 key 的hashCode 值相等,並且 equals() 方法也返回 true,用作鍵的對象必須實現 hashCode 方法和 equals 方法
HashMap、Hashtable
- 動態數組結構+鏈式結構或哈希結構, 由鏈表或紅黑樹結構組成
LinkedHashMap
- 是HashMap的子類,與之不同的在於LinkedHashMap維護着一個運行於所有條目的雙重鏈接列表,此鏈接列表定義了迭代順序,該迭代順序通常就是(插入順序)
TreeMap
- 基於紅黑樹的 NavigableMap 接口實現。該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的 Comparator 進行排序,具體取決於使用的構造方法。
Properties
- 是 Hashtable 的子類,Properties 可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串
Collections 是一個操作 Set、List 和 Map 等集合的工具類
File類:文件和目錄路徑名的抽象表示形式。File
類的實例是不可變的
IO流是用於數據輸入與輸出
1、四大超類,抽象類
(1)InputStream:字節輸入流
(2)OutputStream:字節輸出流
(4)Writer:字符輸出流
2、常見IO流
FileInputStream:文件字節輸入流,可以讀取任意類型的文件
FileOutputStream:文件字節輸出流,可以把字節數據輸出到任意類型的文件
FileReader:文件字符輸入流,只能讀取純文本的文件。按照平台默認的字符編碼進行解碼。
FileWriter:文件字符輸出流,只能把字符數據輸出到純文本文件。按照平台默認的字符編碼進行編碼。
(2)緩沖IO流
String readLine():按行讀取
BufferedWriter:字符輸出緩沖流,給Writer系列IO流增加緩沖效果
void newLine():輸出換行符
void flush()
(3)編碼與解碼的轉換流
編碼:OutputStreamWriter
可以把字符流轉為字節流輸出,並且可以指定字符編碼。
應用場景:可將要寫入的字符源為字節流的數據轉為字符類型寫入並可按指定字符集再編碼成字節存儲
可以把字節輸入流轉為字符輸入流,並且可以指定字符編碼。
應用場景:讀取源為字符類型的字節流可指定字符集解碼成字符流,以便閱讀
(4)數據IO流
它倆必須配對使用,讀的順序要與寫的順序一致
(5)對象IO流,同上也需配對,讀寫順序一致
ObjectOutputStream:對象序列化,輸出對象,把對象轉為字節序列輸出
void writeObject(Object obj)
- 所有要序列化的對象的類型都必須實現java.io.Serializable接口
- 如果對象的屬性類型也是引用數據類型,那么也要實現java.io.Serializable接口
- 希望類的修改對象反序列化不產生影響,需增加一個序列化版本ID
- private static final long serialVersionUID = 1L;
- 如果有些屬性不想要序列化,可以加transient
ObjectInputStream:對象反序列化,讀取對象,把字節序列重構成Java對象
Object readObject()
(6)打印流
PrintStream、PrintWriter:println()和 print()
(7)文本掃描儀
Scanner
Socket:通信的兩端都要有Socket(也可以叫“套接字”),是兩台機器間通信的端點。網絡通信其實就是Socket間的通信。
TCP
-
-
調用 accept() :監聽連接請求,如果客戶端請求連接,則接受連接,返回通信套接字對象。
-
調用 該Socket 類對象的 getOutputStream() 和 getInputStream () :獲取輸出流和輸入流,開始網絡數據的發送和接收。
-
關閉Socket 對象:客戶端訪問結束,關閉通信套接字。
-
-
打開連接到 Socket 的輸入/ 出流: 使用 getInputStream()方法獲得輸入流,使用getOutputStream()方法獲得輸出流,進行數據傳輸
-
按照一定的協議對 Socket 進行讀/ 寫操作:通過輸入流讀取服務器放入線路的信息(但不能讀取自己放入線路的信息),通過輸出流將信息寫入線路。
-
關閉 Socket :斷開客戶端到服務器的連接,釋放線路
類的加載又分為三個階段
(1)加載:load (2)連接:link ①驗證②准備③解析
不會導致類的初始化的情況,其他都會
(1)使用某個類的靜態的常量(static final)
(2)通過子類調用父類的靜態變量,靜態方法,只會導致父類初始化,不會導致子類初始化,即只有聲明靜態成員的類才會初始化
類加載器
(1)引導類加載器(Bootstrap Classloader)又稱為根類加載器
(2)擴展類加載器(Extension ClassLoader)
(3)應用程序類加載器(Application Classloader)
(4)自定義類加載器
(1)類型名.class
(2)對象.getClass()
(3)Class.forName(類型全名稱)
(4)ClassLoader的類加載器對象.loadClass(類型全名稱)
可以獲取:包、修飾符、類型名、父類(包括泛型父類)、父接口(包括泛型父接口)、成員(屬性、構造器、方法)、注解(類上的、方法上的、屬性上的)
1、直接通過Class對象來實例化(要求必須有無參構造)
2、通過獲取構造器對象來進行實例化
(2)獲取屬性對象 Field field = clazz.getDeclaredField("username");
(3)設置屬性可訪問 field.setAccessible(true);
(4)創建實例對象:如果操作的是非靜態屬性,需要創建實例對象 Object obj = clazz.newInstance();
(4)設置屬性值 field.set(obj,"chai");
(5)獲取屬性值 Object value = field.get(obj);
如果操作靜態變量,那么實例對象可以省略,用null表示
(1)獲取該類型的Class對象 Class clazz = Class.forName("com.atguigu.service.UserService");
(2)獲取方法對象 Method method = clazz.getDeclaredMethod("login",String.class,String.class);
(3)創建實例對象 Object obj = clazz.newInstance();
(4)調用方法 Object result = method.invoke(obj,"chai","123);
如果方法的權限修飾符修飾的范圍不可見,也可以調用setAccessible(true)
Lambda
強調做什么,而不是以什么形式做
只要能獲取到結果,誰去做的,怎么做的都不重要,重視的是結果,不重視過程
標記了@FunctionalInterface
Java8新增了四大類,消費型、供給型、判斷型、功能型。
Lambda表達式語法格式
(形參列表) -> {Lambda體}
說明:
-
(形參列表)它就是你要賦值的函數式接口的抽象方法的(形參列表),照抄
-
{Lambda體}就是實現這個抽象方法的方法體
-
->稱為Lambda操作符(減號和大於號中間不能有空格,而且必須是英文狀態下半角輸入方式)
優化:Lambda表達式可以精簡
-
當{Lambda體}中只有一句語句時,可以省略{}和{;}
-
當{Lambda體}中只有一句語句時,並且這個語句還是一個return語句,那么return也可以省略,但是如果{;}沒有省略的話,return是不能省略的
-
(形參列表)的類型可以省略
-
當(形參列表)的形參個數只有一個,那么可以把數據類型和()一起省略,但是形參名不能省略
-
方法引用的語法格式:
(1)實例對象名::實例方法
(2)類名::靜態方法
說明:
-
::稱為方法引用操作符(兩個:中間不能有空格,而且必須英文狀態下半角輸入)
-
Lambda表達式的形參列表,全部在Lambda體中使用上了,要么是作為調用方法的對象,要么是作為方法的實參。
-
構造器引用的語法格式:
-
類名::new
-
數組類型名::new
(1)當Lambda表達式是創建一個對象,並且滿足Lambda表達式形參,正好是給創建這個對象的構造器的實參列表。
(2) 當Lambda表達式是創建一個數組對象,並且滿足Lambda表達式形參,正好是給創建這個數組對象的長度
①Stream 自己不會存儲元素。
②Stream 不會改變源對象。每次處理都會返回一個持有結果的新Stream。
③Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。