包:
- 什么是包? 可以把它理解為一個檔案夾
- 包的作用? 區分相同名稱的類,方便管理類,控制訪問范圍
- 如何創建包?和創建檔案夾一樣
- 如何引入包?語法:import 包 , 如:import java.util.*
- 如果有兩個一樣的類名,就可以提供地址來區分是哪個包下的

-
包的命名規范:
- 只能包含數字,字母,下劃線,小圓點
- 不能以數字開頭,不能用關鍵字,保留字
- 正規格式:com.公司名.專案名.業務名
- com.TX.crud.user
-
常用的包:
- java.lane.* 是java的基礎包,默認匯入不需要引入
- java.util.* java提供的工具包
- java.net.* 網路開發包
- java.awt.* java頁面開發包
-
細節:
- package(打包) - 作用:生明當前類是屬于哪個包
- import(匯入) - 作用:匯入包
訪問修飾符:
- 什么是訪問修飾符? 用于控制方法和屬性的訪問權限
- 訪問修飾符分為:4種訪問修飾
- public - 公共的
- protected - 受保護的
- private - 私有的
- 默認的 - 就是什么都不寫

-
細節:
- 修飾符,可以修飾屬性和方法以及類
- 只有默認和public才能修飾類
- 屬性和成員屬性的訪問完成一樣
-
//細節2:只有默認和public才能修飾類 public class Sds { public int i = 1; //公共 protected int n = 2;//受保護的 int o = 3;//默認的 private int p = 4;//私有的 public void show(){ //方法和屬性的訪問修飾符是一樣的 System.out.println("我是方法show"); } } //細節2:只有默認和public才能修飾類 class King{ }
封裝:
-
什么是封裝? 將類在的某些資訊隱藏在類的內部,不允許外部直接訪問,而是通過類提供的方法來對隱藏的資料進行訪問和操作
-
封裝的好處? 1.只能規定的方法訪問和操作資料 ,2.可以對資料進行驗證,保證安全合理,3.隱藏實作細節
-
封裝的實作步驟:
-
將屬性私有化private
-
提供一個setXxx(引數串列)方法,對屬性進行判斷和賦值
-
提供一個getXxx()方法,獲取屬性值
-
-
public class Test{ private String name; private String sex = "男"; private int age = 18; //獲取屬性值 public String getName() { return name; } public void setName(String name) { //進行判斷和賦值 if(name.length() > 1 && name.length() < 5){ this.name = name; }else { System.out.println("你名稱太長了"); } } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } } main{ Test.setName("jack,彭于晏,吳彥祖");//肯定是錯的,因為條件判斷最大是5 }
-
構造器和Set()方法結合:
-
如果使用構造器來給屬性賦值,那么Set方法的判斷就會失效,直接在構造器中呼叫Set方法就可以經解決
-
-
public Sds2(String name, String sex, int age) { //像使用構造器,就可以直接跳過Set()的判斷了 // this.name = name; // this.sex = sex; //呼叫本類的方法就好set方法就好了 setName(name); setSex(sex); }
繼承:
- 什么是繼承? 符合is a條件的類可以通過繼承來解決代碼的復用,如動物類和小狗類,那么小狗就可以繼承動物類,因為狗有動物的行為
- 為什么需要繼承?減少代碼的復用
-
繼承示意圖:
-
繼承的基本語法:
-
class 子類 extends 父類{ //繼承父類,知道要有父類的屬性和方法 }
-
-
細節:
-
子類繼承了父類,非私有的屬性和方法可以直接在子類訪問,但私有屬性不能直接訪問(需要通過父類的公共方法來訪問)
-
子類必須呼叫父類的構造器,完成父類的初始化(理解:當去繼承父類如果沒呼叫構造器初始化父類,那么繼承的是什么?)
- (簡單理解:父親都沒有,哪來的你?)
- 創建子類物件,不管使用子類哪個構造器,默認會去呼叫父類的無參構造器,如果父類沒有無參構造器,則需要在子類使用super來指定父類構造器,完成父類初始化
- 指定父類構造器方法:super(引數串列)
- super()使用時必須放在構造器第一行(super()只能在構造器中使用),因此super和this都是需要放在第一行的,所以不能同時在一個構造器使用
- java所有類都是Object類的子類,所以父類可以一直追溯到Object
- java是單繼承機制,只能繼承一個父類
- 父類和子類必須滿足is-邏輯,如你是飛機類去繼承汽車類,這不就扯蛋了
-
public static void main(String[] args) { B b= new B(); } class A{ A(){ System.out.println("我是A的無參構造器"); } A(String mame) { System.out.println("我是A的有參構造器"); } } class B extends A{//只能繼承一個父類 B(){ //super();默認呼叫父類的無參構造器 //super("jack");指定父類的構造器 System.out.println("我是b的無參構造器"); } }
-
-
繼承的本質:
- 本質:先去加載父類,在加載子類
- 問題:為什么創建的CarSon指向的堆中有父類的屬性?
- 細節中說到:因為繼承了父類就會獲取子類中非私有的屬性和方法
-
-
Super關鍵字:
-
什么是Super關鍵字? 可以用于直接訪問父類的構造器、方法、屬性
- 理解:本類不訪問直接訪問父類
-
class Car{ String name = "汽車"; String affect = "出行"; } class CarSon extends Car{ String name = "跑車"; String CarName = "Lamborghini"; public void jk(){ System.out.println("CarSon類jk方法"); } public void show(){ System.out.println(affect);//如果沒指定呼叫的是父類的還是子類的,就從子類開始向上找 System.out.println(name);//輸出跑車,這個也等價于this.name System.out.println(super.name);//輸出汽車 } }
-
細節:
-
如不使用super,就從本類向父類查找成員,如果有重名就遵循就近原則,本類沒有才找父類
-
找成員naem,如子類沒有找父類,父類沒有在找爺爺類,A->B->C,當然遵守訪問權限原則
-

-
方法的重寫/覆寫:
-
什么是方法的重寫? 就是子類的某個方法和父類的某個方法,方法名稱、回傳型別、引數串列一樣
-
細節:
-
子類的形參串列,方法名稱,要和父類形參串列,方法名稱完全一樣
-
子類的回傳型別要和父類一致,或保持父子關系,如父類是Object回傳型別,子類是String回傳型別
-
子類不能縮小方法的訪問權限但是可以放大 public > protected > 默認 > private
-
class Car{ public void show(){ System.out.println("我是show方法"); } public Object show2(){ return 1.1; } private void show3(){ System.out.println("我是show3方法"); } } class CarSon extends Car{ //子類的形參串列,方法名稱,要和父類形參串列,方法名稱完全一樣 public void show(){ System.out.println("我是子類,我重寫了show方法"); } //子類的回傳型別要和父類一致,或保持父子關系,如父類是Object子類是String public String show2(){ return "1.1"; } //子類不能縮小方法的訪問權限但是可以放大 public > protected > 默認 > private public void show3(){ System.out.println("我是子類,我重寫了show3方法"); } }
-
-

多型:
- 什么是多型? 多種形態,多型是建立在繼承和封裝的基層上
- 理解:完成某個行為的時候,不同的物件去完成會產生不同的狀態
- 例子:方法的重寫和多載就是多型的一種體現 -> 方法的多型
- 如父類參考=子類物件( 如:Animal animal = new Dog() ) - > 物件的多型
-
物件的多型:
- Animal animal = new Animal( ) - -> 左邊是編譯型別 - 右邊是運行型別
- 一個物件的編譯型別和運行型別可以不一致,當然只兩者要保持繼承關系
- 編譯型別在確定物件后是不能改變的,運行型別可以改變
- 下面案例中就使用物件的多型完成了動物的喂食問題
- 小狗有父類,食物有父類,通過小狗和食物的父類編譯型別去參考它的子類物件完成操作
-
public class Test { public static void main(String[] args) { person person = new person("湯姆"); Dog2 dog2 = new Dog2("小白"); Bone2 bone2 = new Bone2("骨頭"); person.show4(dog2,bone2); //解決:用到多型物件就完美的解決該問題喂食方法的重復問題 Cat2 cat2 = new Cat2("小花"); Bone2 bone3 = new Bone2("骨頭"); person.show5(cat2,bone3); } } //目的:讓人去給動物喂食物 class Animal2{ private String name; public Animal2(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Fish2{ private String name; public Fish2(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Dog2 extends Animal2{ public Dog2(String name) { super(name); } } class Cat2 extends Animal2{ public Cat2(String name) { super(name); } } class Bone2 extends Fish2{ public Bone2(String name) { super(name); } } class person{ public person(String name) { this.name = name; } private String name;//主人名稱 //問題:如果我有一百種小動物,那我的喂食方法也需要寫一百個嗎 public void show4(Dog2 dog2,Bone2 bone2){ //喂食方法 System.out.println("主人"+name+"給"+dog2.getName()+"吃"+bone2.getName()); } //解決:用到多型物件就完美的解決該問題 public void show5(Animal2 animal2,Fish2 fish2){ //喂食方法 System.out.println("主人"+name+"給"+animal2.getName()+"吃"+fish2.getName()); } }
-
多型向上轉型:
- 什么是向上轉型? 子類是運行型別,父類是編譯型別
- 細節:
- 不能呼叫本身的特有成員,可以呼叫父類的所有成員(遵守訪問權限)
- 為什么不能呼叫本身特有成員? 因為在編譯階段,能呼叫哪些成員,是由編譯型別決定(說白了就是加載編譯型別的成員變數)
- 因為最終的的運行看子類的具體表現
- 因為最終的的運行看子類的具體表現什么意思? - 呼叫成員時還是按子類向父類的向上查找
- 不能呼叫本身的特有成員,可以呼叫父類的所有成員(遵守訪問權限)
-
public class Test { public static void main(String[] args) { //普通繼承 - 可以呼叫本身特有的成員,和父類中所有的成員(遵守訪問權限) Dog2 dog2 = new Dog2(); dog2.eat();//吃骨頭 dog2.action(); dog2.show(); //多型向上轉型 - 不能呼叫本身的特有成員,可以呼叫父類的所有成員(遵守訪問權限) //為什么不能呼叫本身特有成員? 因為在編譯階段,能呼叫哪些成員,是由編譯型別決定(說白了就是加載編譯型別的成員變數) //Animal2是編譯型別,Dog2是運行型別 //為什么animal2.eat();輸出吃骨頭不是吃東西? - 因為最終的的運行看子類的具體表現 //因為最終的的運行看子類的具體表現什么意思? - 呼叫成員時還是按子類向父類的向上查找 Animal2 animal2 = new Dog2(); animal2.eat();//吃骨頭 } } class Animal2{ public void eat(){ System.out.println("吃東西"); } public void action(){ System.out.println("撒嬌"); } } class Dog2 extends Animal2{ public void eat(){ System.out.println("吃骨頭"); } public void show(){ System.out.println("展示才藝"); } }
-
多型向下轉型:
-
什么是向下轉型? 把父類的的參考強轉,為編譯型別是子類的物件( 如:Dog dog = (Dog)animal )
-
細節:
-
只能強轉父類的參考,終于不是父類的物件
-
強轉的父類參考必須是和當前物件有關聯的
-
向下轉型后,可以呼叫子類中所有的成員
-
-
Animal2 animal2 = new Dog2(); animal2.eat();//吃骨頭 //多型的向下轉型 - 強轉需要保持關聯性 //當初是Dog2向上轉型為父類的animal2,那么向下轉型也要保持這個關系 Dog2 dog3 = (Dog2) animal2; og3.show();
-
-
屬性沒有重寫之說:
- 屬性的值看編譯型別 -
-
public class Test { public static void main(String[] args) { A a = new B(); System.out.println(a.name);//MIUI B b = new B(); System.out.println(b.name);//Huawei } } class A{ public String name = "MIUI"; } class B extends A{ public String name = "Huawei"; }
-
instanceOf比較運算子:
-
用與判斷物件的運行型別是否為XX型別或XX型別的子型別
-
public class Test { public static void main(String[] args) { A a = new A(); System.out.println(a instanceof A);//真 A a2 = new B(); B b = new B(); System.out.println(b instanceof A);//真 } } class A{ public String name = "MIUI"; } class B extends A{ public String name = "Huawei"; }
-
-
java的動態系結機制(重點):
- 什么是動態系結機制?
- 當呼叫物件方法的時候,該方法會和該物件的記憶體地址/運行型別系結
- 當呼叫物件屬性時,沒有動態系結機制,哪里宣告哪里使用
- 什么是動態系結機制?
-
public class Test { public static void main(String[] args) { A a = new B(); //沒有把B類中的sum()方法注銷時的輸出結果 System.out.println(a.sum());//220 System.out.println(a.sum1());//210 //把B類中的sum()方法注銷后輸出的結果 //為什么是210? 因為地態系結機制的原因,呼叫到getl()時就回到運行型別的呼叫,沒有該方法在往上尋找 System.out.println(a.sum());//210 System.out.println(a.sum1());//210 } } class A{ public int a = 100; public int sum(){ return getl() + 10; } public int sum1(){ return a + 10; } public int getl(){ return a; } } class B extends A{ public int a = 200; // public int sum(){ // return a + 20; // } public int sum1(){ return a + 10; } public int getl(){ return a; } }
-
多型陣列:
- 什么是多型陣列? 在一個陣列中可以存放不同的子類
- 案例:
-
public class Test { public static void main(String[] args) { Person[] person = new Person[5]; person[0] = new Student("小白",18,"學生"); person[1] = new Teacher("老王",32,"老師"); for (int i = 0; i < person.length; i++) { //show方法是重寫的 - 但運行結果是根據運行型別 if(person[i] != null){ String show = person[i].show(); System.out.println(show); //向下轉型,呼叫特有的成員 if(person[i] instanceof Student){ System.out.println(((Student)person[i]).study()); } if(person[i] instanceof Teacher){ System.out.println(((Teacher)person[i]).teach()); } } } } } class Person{ public Person(String name, int age) { this.name = name; this.age = age; } private String name; private int age; public String show(){ return name+"-"+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; } } class Student extends Person{ public Student(String name, int age, String job) { super(name, age); this.job = job; } private String job; public String show(){ return super.show()+"-"+job; } public String study(){ return super.getName()+"在收聽java"; } } class Teacher extends Person{ public Teacher(String name, int age, String job) { super(name, age); this.job = job; } private String job; public String show(){ return super.show()+"-"+job; } public String teach(){ return super.getName()+"給學生將java"; } }
Object頂級父類下的常見方法:
-
equals方法:
-
equlas:是Object類中的方法,默認(沒被重寫時)是判斷參考型別的地址是否相等,子類往往重寫該方法用與判斷內容是否相等(如String和Integer)
-
一般 equals 和 == 會進行一個比較(面試):
-
== :是一個比較運算子
-
== :即可以判斷該基本資料型別,又可以判參考型別
-
==:判斷基本資料型別判斷該的值,判斷的是參考型別判斷該的是地址
-
-
重寫equals方法:
-
public class Test { public static void main(String[] args) { Person person1 = new Person("小白",18,'男'); Person person = new Person("小白",18,'男'); // System.out.println(person1.equals(person));//false(沒有重寫equals默認比較地址) System.out.println(person1.equals(person));//true(重寫equals后) } } class Person{ public Person(String name, int age, char sex) { this.name = name; this.age = age; this.sex = sex; } String name; int age; char sex; public boolean equals(Object obj) { //this代表的就是obj(自己呼叫我自己) if(this == obj){ return true; } if(obj instanceof Person){ Person p = (Person)obj; return this.name == p.name && this.age == p.age && this.sex == p.sex; } return false; } }
-
-
hashCode方法:
- hashCode回傳的是哈希碼值,支持該方法是為了提高哈希表
- 哈希值主要根據地址類(但哈希值不完全等價于地址,因為Object的hashCode方法會根據不同的物件回傳不同的整數)
- 兩給參考,指向的是同一個物件,則哈希值肯定是一樣,反知
-
public class Test { public static void main(String[] args) { Person person1 = new Person("小白"); Person person2 = new Person("小紅"); System.out.println(person1.hashCode());//356573597 System.out.println(person2.hashCode());//1735600054 } } class Person{ public Person(String name) { this.name = name; } String name;
- toString方法:
- 默認回傳:全類名+@+哈希值的十六進制
- 一般子類重寫用來回傳物件的屬性資訊,列印物件或拼接物件時,都會該方法會自動呼叫
-
public class Test { public static void main(String[] args) { Person person1 = new Person("小白","打游戲"); // System.out.println(person1.toString());//默認輸出 System.out.println(person1);//重寫輸出:Person{name='小白', hobby='打游戲'} } } class Person{ public Person(String name, String hobby) { this.name = name; this.hobby = hobby; } String name; String hobby; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", hobby='" + hobby + '\'' + '}'; } }
-
finalize方法:
-
finalize方法是做什么的? 當物件被回收時,系統自動呼叫該方法(注意不是該方法用來回收物件,而是在被回收前做一些操作)
-
什么時候被回收?當物件沒有參考指向它時,jvm認為該物件就是一個垃圾物件,就會使用垃圾回識訓制來銷毀該物件,在銷毀前會呼叫finalize方法
-
垃圾回識訓制?是由GC演算法來決定(也就是說物件沒參考的時候就馬上銷毀,而是由GC演算法決定的),但是可以通過System.gc();來主動觸發垃圾回識訓制
-
public class Test { public static void main(String[] args) { BaoMa baoMa = new BaoMa("寶馬"); baoMa = null; System.gc();//主動呼叫垃圾回識訓制 System.out.println("程式退出"); } } class BaoMa{ public BaoMa(String name) { this.name = name; } String name; @Override protected void finalize() throws Throwable { System.out.println("銷毀汽車"+name); System.out.println("釋放資源"); } }
-
斷點除錯:
- 什么是斷點除錯? 通過一行一行的去執行代碼,查看代碼的執行

- 類加載的斷點除錯演示:
-

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/505451.html
標籤:Java

