[toc]
== 和 equals 的對比
== 是一個比較運算符
1、== : 既可以判斷類型,又可以判斷引用類型
2、== :判斷基本類型,判斷的是值是否相等
3、== :如果是引用類型,判斷的是地址是否相等,即判定是不是同一個對象
equals
1、equals :是object 類中的方法,只能判斷引用類型,
2、equals :默認(rèn)判斷的是地址是否相等,子類中往往重寫該方法(public boolean equals(object obj) ) 用于判斷內(nèi)容是否相等,
Java hashCode
1、提高具有哈希結(jié)構(gòu)的效率
2、兩個引用,如果指向的是同一個對象,則哈希值肯定是一樣的!
3、兩個引用,如果指向的是不同對象,則哈希值是不一樣的
4、哈希值主要根據(jù)地址號來的!,不能完全將哈希值等價于地址
5、集合中hashCode 按需重寫
Java 的動態(tài)綁定機制
B 是 A 的子類 , A a = new B()
a 在編譯類型是 A (等號左邊) ,運行類型是 B (等號右邊)
1、當(dāng)調(diào)用對象的方法的時候,該方法會和該對象的內(nèi)存地址進行綁定
2、當(dāng)調(diào)用對象屬性時,沒有動態(tài)綁定機制,哪里有聲明,哪里使用
接口
implements 實現(xiàn)接口
extends 繼承
1、JDK 7.0 以前,接口里的所有方法都沒有方法體,即都是抽象方法
2、JDK 8.0 后,接口可以有靜態(tài)方法,默認(rèn)方法,也就是說接口中可以有方法的具體實現(xiàn)(default 關(guān)鍵字修飾)
3、一個類可以實現(xiàn)多接口 implements A ,B
4、接口中的屬性,只能是final的。而且是 public static final
5、接口中屬性的訪問形式 : 接口明. 屬性名
6、接口不能繼承其他類,但是可以繼承多個別的接口
7、接口的修飾符 只能是 public 和 默認(rèn),這點和類的修飾符是一樣的
代碼塊
1、static 代碼塊也叫靜態(tài)代碼塊,作用就是對類進行初始化,而且他隨著類的加載而執(zhí)行,并且只會執(zhí)行一次。如果是普通代碼塊,沒創(chuàng)建一個對象,就執(zhí)行一次。
2、類什么時候被加載【需要背】
- 1、創(chuàng)建對象實例時(new)
- 2、創(chuàng)建子類對象實例,父類也會被加載
- 3、使用類的靜態(tài)成員時(靜態(tài)屬性、靜態(tài)方法)
3、普通代碼塊,在創(chuàng)建累的實例時,會被隱式調(diào)用。被創(chuàng)建一次,就會被調(diào)用一次。如果只是使用類的靜態(tài)成員時,普通代碼塊并不會被調(diào)用
note:
1、staitc 代碼塊是在類加載時執(zhí)行,且只會執(zhí)行一次
2、普通代碼塊是在創(chuàng)建對象時調(diào)用的,創(chuàng)建一次就會調(diào)用一次
3、類加載的三種情況,需要記?。。。?/p>
創(chuàng)建一個類時,在一個類 調(diào)用的順序是:(重點,難點)
1、調(diào)用靜態(tài)代碼塊和靜態(tài)屬性初始化(注意:靜態(tài)代碼塊和靜態(tài)屬性初始化調(diào)用的優(yōu)先級是一樣的,如果有多個靜態(tài)代碼塊和多個靜態(tài)變量初始化,則按著他們的定義順序進行調(diào)用)
2、調(diào)用普通代碼塊和普通屬性初始化方法(注意:普通代碼塊和蒲絨屬性調(diào)用的優(yōu)先級是一樣的,按定義順序調(diào)用)
3、調(diào)用構(gòu)造方法
創(chuàng)建一個子類(繼承關(guān)系),他們的靜態(tài)代碼塊,靜態(tài)屬性初始化,普通代碼塊,普通屬性初始化,構(gòu)造方法的調(diào)用順序如下:
1、父類的靜態(tài)代碼塊和靜態(tài)屬性,按順序執(zhí)行
2、子類的靜態(tài)代碼塊和靜態(tài)屬性,按順序執(zhí)行
3、父類的普通代碼塊和普通類屬性,按執(zhí)行順序執(zhí)行
4、父類的構(gòu)造方法
5、子類的普通代碼塊和普通類屬性,按順序執(zhí)行
6、子類的構(gòu)造方法
靜態(tài)、非靜態(tài) 方法調(diào)用
靜態(tài)代碼塊只能直接調(diào)用靜態(tài)成員(靜態(tài)屬性和靜態(tài)方法),普通代碼塊可以調(diào)用任意成員
內(nèi)部類
一個類內(nèi)部又完整嵌套了另一個類結(jié)構(gòu)。被嵌套的類稱為內(nèi)部類,嵌套其他類的類稱為外部類。使我們類的第五大成員【五大成員:
屬性、方法、構(gòu)造器、代碼塊、內(nèi)部類】,內(nèi)部類最大特點就是可以直接訪問私有屬性,并且可以體現(xiàn)類與類之間的包含關(guān)系
class Outer { // 外部類
class Inner{ // 內(nèi)部類
}
}
class Other{ // 其他類
}
內(nèi)部類分類
定義在外部類局部位置上(比如方法上)
package com.zhao.smallchange;
public class Outer {
private int age = 23;
public static void main(String[] args) {
new Outer().innerAction();
}
public void innerAction(){
class innerClass{
private int age = 12;
public void sayAge(){
System.out.println("內(nèi)部類age:" + age + "外部類age:" + Outer.this.age );
}
}
innerClass innerClass = new innerClass();
innerClass.sayAge();
}
}
1、局部內(nèi)部類 (有類名)
1、局部內(nèi)部類是定義在外部類的局部位置,通常在方法、代碼塊中
2、可以直接訪問外部類的多有成員,包含私有的
3、不能添加訪問修飾符,但是可以使用final修飾
4、作用域: 僅僅在定義它的方法或者代碼塊中
5、局部內(nèi)部類可以直接訪問外部類的成員,比如 方法和屬性
6、外部類在方法中,可以創(chuàng)建 內(nèi)部類 對象,讓后調(diào)用方法即可
7、外部其他類 不能訪問 局部內(nèi)部類 (因為 內(nèi)部類地位是一個局部變量)
8、如果外部類和局部內(nèi)部類成員變量重名時,默認(rèn)遵循就近原則,如果想訪問外部類的成員變量,則可以使用 (外部類名.this.成員) 去訪問
2、匿名內(nèi)部類(沒有類名,重點?。。?/strong>
new 類或者接口(參數(shù)列表){
類的相關(guān)實現(xiàn)
};
// 實際使用
package com.zhao.smallchange;
public class Outer {
public static void main(String[] args) {
new Outer().innerAction(new OuterInterface() {
@Override
public void sayHello() {
System.out.println("我是匿名內(nèi)部類");
}
});
}
public void innerAction(OuterInterface subInterface){
subInterface.sayHello();
}
}
interface OuterInterface{
public void sayHello();
}
定義在外部類的成員位置上
package com.zhao.smallchange;
public class Outer {
private int n1 = 10;
public String name = "張三";
public static void main(String[] args) {
new Outer().t1();
}
class InnerClass{
public void say(){
System.out.println("n1 = " + n1 + " name =" + name);
}
}
public void t1(){
InnerClass innerClass = new InnerClass();
innerClass.say();
}
}
1、成員內(nèi)部類(沒有static修飾)
- 1、可以直接訪問外部類的成員變量,包含私有
- 2、可以添加任意訪問修飾符( public、protected、默認(rèn)、private ),因為它的地位就是一個成員。
- 3、作用域 : 和外部類的其他成員一樣,為整個類
- 4、成員內(nèi)部類 --> 訪問外部類成員 ,直接訪問
- 5、外部類 --> 訪問內(nèi)部類,創(chuàng)建內(nèi)部類對象,并訪問
- 6、其他外部類 --> 訪問 --> 成員內(nèi)部類
- 6.1、第一種方式
public static void main(String[] args) { InnerClass innerClass = new Outer().new InnerClass(); }- 6.2、第二種方式,通過一個方法返回內(nèi)部類對象
public static void main(String[] args) { InnerClass innerClass1 = new Outer().getInnerClass(); } public InnerClass getInnerClass(){ return new InnerClass(); }
-7、如果內(nèi)部類成員變量 和 外部類成員變量 沖突,外部類還是 外部類.this.成員變量
2、靜態(tài)內(nèi)部類(使用static修飾)
class Outer10{
private int n1 = 10;
private static String name = "張三";
static class Inner10{
}
}
1、放在外部類成員位置
2、使用 static 修飾
3、可以訪問外部類的所有成員變量,包含私有的,但不能直接訪問非靜態(tài)變量
4、可以添加任意訪問修飾符 (public、protected、默認(rèn) 、private),但是不能直接訪問非靜態(tài)成員變量
// 第一種: 對象調(diào)用
package com.zhao.smallchange;
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10.Inner10 inner10 = new Outer10.Inner10();
}
}
class Outer10{
private int n1 = 10;
private static String name = "張三";
static class Inner10{
}
}
// 第二種: 普通方法暴露
package com.zhao.smallchange;
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10.Inner10 staticInnerClass = new Outer10().getStaticInnerClass();
}
}
class Outer10{
private int n1 = 10;
private static String name = "張三";
static class Inner10{
}
public Inner10 getStaticInnerClass(){
return new Inner10();
}
}
// 第三種:static 方法
package com.zhao.smallchange;
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10.Inner10 staticInnerClass = Outer10.getStaticInnerClass();
}
}
class Outer10{
private int n1 = 10;
private static String name = "張三";
static class Inner10{
}
public static Inner10 getStaticInnerClass(){
return new Inner10();
}
}
5、作用域 整個類
6、如果外部類和靜態(tài)內(nèi)部類的成員重名是,靜態(tài)內(nèi)部類訪問的時候,默認(rèn)遵循就近原則,如果想訪問外部類的成員,則可以使用 (外部類.成員)去訪問
String、StringBuilder、StringBuffer 選擇
- 1、如果字符串存在大量的修改操作,一般使用StringBuilder 和 StringBuffer
- 2、如果字符串存在大量的修改操作,并在單線程情況下,使用StringBuilder
- 3、如果字符串存在大量的修改操作,并在多線程情況下,使用StringBuffer
- 4、如果我們字符串很少修改,被多個對象引用,使用String。比如配置信息
random 隨機數(shù)
返回的是 0 <= x < 1 之間的隨機小數(shù)
- 1、[2 7] 隨機整數(shù) (int)(a + Math.random() * (b - a + 1))
- 2、[2 7) 隨機整數(shù) (int)(a + Math.random() * (b - a))
public static void main(String[] args) {
// 思考:請寫出獲取 a, b 之間的一個隨機整數(shù),a = 2 b = 7
// 1、 [0 10) 隨機數(shù)
System.out.println("=========[0 10) 隨機數(shù)===========");
for (int i = 0; i < 10; i++) {
System.out.println(10 * Math.random());
}
// 2、 [0 10) 隨機整數(shù)
System.out.println("=========[0 10) 隨機整數(shù)===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(10 * random);
System.out.println((int)(10 * random));
}
// 3、[2 12) 隨機整數(shù)
System.out.println("=========[2 12) 隨機整數(shù)===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(10 * random + 2);
System.out.println((int)((12 - 2) * random + 2));
}
// 4、[2 7) 隨機整數(shù)
System.out.println("=========[2 7) 隨機整數(shù)===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(5 * random + 2);
System.out.println((int)((7 - 2) * random + 2));
}
// 5、[2 7]隨機整數(shù) == [2 8)隨機整數(shù)
System.out.println("=========[2 7] 隨機整數(shù)===========");
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println((8 - 2) * random + 2);
System.out.println((int)((1 + (7 - 2)) * random + 2));
}
集合實現(xiàn)類的選擇
-
1、一組對象:Collection 接口
- 允許重復(fù):List
增刪多:LinkedList 底層維護了一個雙向鏈表
改查多:ArrayList 底層維護 Object類型的可變數(shù)組 - 不允許重復(fù):Set
無序:HashSet 底層是HashMap,維護了一個哈希表 即(數(shù)組 + 鏈表 + 紅黑樹)
排序:TreeSet
插入和取出順序一致:LinkedHashSet,維護數(shù)組 + 雙向鏈表
- 允許重復(fù):List
-
2、一組鍵值對
- 1、鍵無序:HashMap 底層是: 哈希表 jdk7: 數(shù)組 + 鏈表 jdk8:數(shù)組 + 鏈表 + 紅黑樹
- 2、鍵排序:TreeMap
- 3、鍵插入和取出順序一致:LinkedHashMap
- 4、讀取文件 Properties
Thread 和 Runnable
- 1、從Java 設(shè)計上來看,通過繼承Thread或者實現(xiàn)Runnable 接口來創(chuàng)建線程本質(zhì)上是沒有區(qū)別的,Thread 類本身就實現(xiàn)了 Runnable 接口
- 2、實現(xiàn)Runnable 接口方式更加適合多個線程共享一個資源的情況,并且避免了繼承的限制
package com.zhao.learn01;
public class Learn {
public static void main(String[] args) {
T3 t3 = new T3();
Thread thread1 = new Thread(t3);
Thread thread2 = new Thread(t3);
thread1.start();
thread2.start();
}
}
class T3 implements Runnable{
@Override
public void run() {
// 進行線程操作
}
}
線程常用方法
- 1、setName : 設(shè)置線程名稱,使之與參數(shù)name相同
- 2、getName:返回該線程的名稱
- 3、start:使該線程開始執(zhí)行;java虛擬機底層調(diào)用線程 start0 方法
- 4、run:調(diào)用線程對象 run 方法
- 5、setPriority:更改線程優(yōu)先級
- 6、getPrority:獲取線程優(yōu)先級
- 7、sleep:在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行)
- 8、interrupt :中斷線程
- 9、yield:線程的禮讓,讓出CPU讓其他線程執(zhí)行。但是禮讓時間不確定,所以也不確定成功
- 10、join:線程的插隊,插隊線程一旦插隊成功,則肯定先執(zhí)行完插入線程的所有任務(wù)
note:
- 1、start 底層會創(chuàng)建新的線程,并調(diào)用run,run就是一個簡單的方法調(diào)用,不會啟動新的線程
- 2、線程優(yōu)先級范圍
- 3、interrupt,中斷線程,但沒有真正的結(jié)束線程。所以一般用于中斷正在休眠的線程
- 4、sleep 線程的靜態(tài)方法,使當(dāng)前線程休眠