吉林省建設(shè)監(jiān)理協(xié)會網(wǎng)站誠信建設(shè)競價推廣代運營
1. 類和對象的內(nèi)存分配機制
1.1 分配機制
? Java 內(nèi)存的結(jié)構(gòu)分析
- 棧: 一般存放基本數(shù)據(jù)類型(局部變量)
- 堆: 存放對象(Cat cat , 數(shù)組等)
- 方法區(qū):常量池(常量,比如字符串), 類加載信息
- 示意圖 [Cat (name, age, price)]
? Java 創(chuàng)建對象的流程簡單分析
Person p = new Person();
p.name = “jack”;
p.age = 10
說明:
- 先加載 Person 類信息(屬性和方法信息, 只會加載一次)
- 在堆中分配空間, 進行默認(rèn)初始化(看規(guī)則)
- 把地址賦給 p , p 就指向?qū)ο?/li>
- 進行指定初始化, 比如 p.name =”jack” p.age = 10
2. 繼承
2.1 super、this只能使用在構(gòu)造方法中
super 在使用時,必須放在構(gòu)造器第一行(super 只能在構(gòu)造器中使用)
class Student{public Student(){}public Student(int a){this(); // 可以 調(diào)用無參構(gòu)造}public void create(){//super(); //錯誤,super只能在構(gòu)造方法中調(diào)用}
}
2.2 繼承內(nèi)存機制
package com.hspedu.extend_;/*** 講解繼承的本質(zhì)*/
public class ExtendsTheory {public static void main(String[] args) {Son son = new Son();//內(nèi)存的布局//?-> 這時請大家注意,要按照查找關(guān)系來返回信息//(1) 首先看子類是否有該屬性//(2) 如果子類有這個屬性,并且可以訪問,則返回信息//(3) 如果子類沒有這個屬性,就看父類有沒有這個屬性(如果父類有該屬性,并且可以訪問,就返回信息..)//(4) 如果父類沒有就按照(3)的規(guī)則,繼續(xù)找上級父類,直到Object...System.out.println(son.name);//返回就是大頭兒子//System.out.println(son.age);//返回的就是39//System.out.println(son.getAge());//返回的就是39System.out.println(son.hobby);//返回的就是旅游}
}class GrandPa { //爺類String name = "大頭爺爺";String hobby = "旅游";
}class Father extends GrandPa {//父類String name = "大頭爸爸";private int age = 39;public int getAge() {return age;}
}class Son extends Father { //子類String name = "大頭兒子";
}
補充:
如果一個類的上一級父類有一個屬性被private修飾,那么將無法訪問該資源,即使這個類的爺爺類有也不能訪問
2.3 重寫和重載的區(qū)別
2.4 this 和 super的區(qū)別
3. 多態(tài)
3.1 細(xì)節(jié)補充
屬性沒有重寫之說!屬性的值看編譯類型
3.2 動態(tài)綁定機制
package com.hspedu.poly_.dynamic_;public class DynamicBinding {public static void main(String[] args) {//a 的編譯類型 A, 運行類型 BA a = new B();//向上轉(zhuǎn)型System.out.println(a.sum());//?40 -> 30System.out.println(a.sum1());//?30-> 20}
}class A {//父類public int i = 10;//動態(tài)綁定機制:public int sum() {//父類sum()return getI() + 10;//20 + 10}public int sum1() {//父類sum1()return i + 10;//10 + 10}public int getI() {//父類getIreturn i;}
}class B extends A {//子類public int i = 20;// public int sum() {
// return i + 20;
// }public int getI() {//子類getI()return i;}// public int sum1() {
// return i + 10;
// }
}
4. Object
4.1 equals方法
package com.hspedu.object_;public class Equals01 {public static void main(String[] args) {A a = new A();A b = a;A c = b;System.out.println(a == c);//trueSystem.out.println(b == c);//trueB bObj = a;System.out.println(bObj == c);//trueint num1 = 10;double num2 = 10.0;System.out.println(num1 == num2);//基本數(shù)據(jù)類型,判斷值是否相等//equals 方法,源碼怎么查看.//把光標(biāo)放在equals方法,直接輸入ctrl+b//如果你使用不了. 自己配置. 即可使用./*//帶大家看看Jdk的源碼 String類的 equals方法//把Object的equals方法重寫了,變成了比較兩個字符串值是否相同public boolean equals(Object anObject) {if (this == anObject) {//如果是同一個對象return true;//返回true}if (anObject instanceof String) {//判斷類型String anotherString = (String)anObject;//向下轉(zhuǎn)型int n = value.length;if (n == anotherString.value.length) {//如果長度相同char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {//然后一個一個的比較字符if (v1[i] != v2[i])return false;i++;}return true;//如果兩個字符串的所有字符都相等,則返回true}}return false;//如果比較的不是字符串,則直接返回false}*/"hello".equals("abc");//看看Object類的 equals 是/*//即Object 的equals 方法默認(rèn)就是比較對象地址是否相同//也就是判斷兩個對象是不是同一個對象.public boolean equals(Object obj) {return (this == obj);}*//*//從源碼可以看到 Integer 也重寫了Object的equals方法,//變成了判斷兩個值是否相同public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;}*/Integer integer1 = new Integer(1000);Integer integer2 = new Integer(1000);System.out.println(integer1 == integer2);//falseSystem.out.println(integer1.equals(integer2));//trueString str1 = new String("hspedu");String str2 = new String("hspedu");System.out.println(str1 == str2);//falseSystem.out.println(str1.equals(str2));//true}
}class B {}
class A extends B {}
4.2 finalize 方法
- 當(dāng)對象被回收時,系統(tǒng)自動調(diào)用該對象的 finalize 方法。子類可以重寫該方法,做一些釋放資源的操作
- 什么時候被回收:當(dāng)某個對象沒有任何引用時,則 jvm 就認(rèn)為這個對象是一個垃圾對象,就會使用垃圾回收機制來
銷毀該對象,在銷毀該對象前,會先調(diào)用 finalize 方法。 - 垃圾回收機制的調(diào)用,是由系統(tǒng)來決定(即有自己的 GC 算法), 也可以通過 System.gc() 主動觸發(fā)垃圾回收機制
5. 靜態(tài)方法(類方法)細(xì)節(jié)
package com.hspedu.static_;public class StaticMethodDetail {public static void main(String[] args) {D.hi();//ok//非靜態(tài)方法,不能通過類名調(diào)用//D.say();, 錯誤,需要先創(chuàng)建對象,再調(diào)用new D().say();//可以}
}
class D {private int n1 = 100;private static int n2 = 200;public void say() {//非靜態(tài)方法,普通方法}public static void hi() {//靜態(tài)方法,類方法//類方法中不允許使用和對象有關(guān)的關(guān)鍵字,//比如this和super。普通方法(成員方法)可以。//System.out.println(this.n1);}//類方法(靜態(tài)方法)中 只能訪問 靜態(tài)變量 或靜態(tài)方法//口訣:靜態(tài)方法只能訪問靜態(tài)成員.public static void hello() {System.out.println(n2);System.out.println(D.n2);//System.out.println(this.n2);不能使用hi();//OK//say();//錯誤}//普通成員方法,既可以訪問 非靜態(tài)成員,也可以訪問靜態(tài)成員//小結(jié): 非靜態(tài)方法可以訪問 靜態(tài)成員和非靜態(tài)成員public void ok() {//非靜態(tài)成員System.out.println(n1);say();//靜態(tài)成員System.out.println(n2);hello();}
}
5.1 構(gòu)造方法可以調(diào)用靜態(tài)和非靜態(tài)資源
class Person {private int id;private static int total = 0;public static int getTotalPerson() {//id++;//錯誤, 注銷return total;}public Person() {//構(gòu)造器total++; //total = 1id = total;//id = 1}
}
class TestPerson {public static void main(String[] args) {System.out.println("Number of total is " +Person.getTotalPerson()); //0Person p1 = new Person();System.out.println( "Number of total is "+ Person.getTotalPerson()); //1}
}
5.2 static修飾的方法不可以使用this/super等關(guān)鍵字
class Person { private int id;private static int total = 0;public static void setTotalPerson(int total){// this.total = total;//錯誤,因為在static方法中,不可以使用this 關(guān)鍵字Person.total = total;}public Person() {//構(gòu)造器total++;id = total;}//編寫一個方法,輸出total的值public static void m() {System.out.println("total的值=" + total);}
}
class TestPerson {public static void main(String[] args) {Person.setTotalPerson(3);new Person(); //最后 total的值就是4Person.m();//看看輸出的是不是4}
}
小結(jié):
記住兩句話
(1) 靜態(tài)方法,只能訪問靜態(tài)成員
(2) 非靜態(tài)方法,可以訪問所有的成員
(3) 在編寫代碼時,仍然要遵守訪問權(quán)限規(guī)則
5. 代碼塊
5.1 細(xì)節(jié)補充
package com.hspedu.codeblock_;public class CodeBlockDetail01 {public static void main(String[] args) {//類被加載的情況舉例//1. 創(chuàng)建對象實例時(new)// AA aa = new AA();//2. 創(chuàng)建子類對象實例,父類也會被加載, 而且,父類先被加載,子類后被加載// AA aa2 = new AA();//3. 使用類的靜態(tài)成員時(靜態(tài)屬性,靜態(tài)方法)// System.out.println(Cat.n1);//static代碼塊,是在類加載時,執(zhí)行的,而且只會執(zhí)行一次.
// DD dd = new DD();
// DD dd1 = new DD();//普通的代碼塊,在創(chuàng)建對象實例時,會被隱式的調(diào)用。// 被創(chuàng)建一次,就會調(diào)用一次。// 如果只是使用類的靜態(tài)成員時,普通代碼塊并不會執(zhí)行System.out.println(DD.n1);//8888, 靜態(tài)模塊塊一定會執(zhí)行}
}class DD {public static int n1 = 8888;//靜態(tài)屬性//靜態(tài)代碼塊static {System.out.println("DD 的靜態(tài)代碼1被執(zhí)行...");//}//普通代碼塊, 在new 對象時,被調(diào)用,而且是每創(chuàng)建一個對象,就調(diào)用一次//可以這樣簡單的,理解 普通代碼塊是構(gòu)造器的補充{System.out.println("DD 的普通代碼塊...");}
}class Animal {//靜態(tài)代碼塊static {System.out.println("Animal 的靜態(tài)代碼1被執(zhí)行...");//}
}class Cat extends Animal {public static int n1 = 999;//靜態(tài)屬性//靜態(tài)代碼塊static {System.out.println("Cat 的靜態(tài)代碼1被執(zhí)行...");//}
}class BB {//靜態(tài)代碼塊static {System.out.println("BB 的靜態(tài)代碼1被執(zhí)行...");//1}
}class AA extends BB {//靜態(tài)代碼塊static {System.out.println("AA 的靜態(tài)代碼1被執(zhí)行...");//2}
}
5.2 靜態(tài)代碼塊只能調(diào)用靜態(tài)成員
6. 各方法代碼塊之間的執(zhí)行順序
package com.hspedu.codeblock_;public class CodeBlockDetail04 {public static void main(String[] args) {//老師說明//(1) 進行類的加載//1.1 先加載 父類 A02 1.2 再加載 B02//(2) 創(chuàng)建對象//2.1 從子類的構(gòu)造器開始//new B02();//對象new C02();}
}class A02 { //父類private static int n1 = getVal01();static {System.out.println("A02的一個靜態(tài)代碼塊..");//(2)}{System.out.println("A02的第一個普通代碼塊..");//(5)}public int n3 = getVal02();//普通屬性的初始化public static int getVal01() {System.out.println("getVal01");//(1)return 10;}public int getVal02() {System.out.println("getVal02");//(6)return 10;}public A02() {//構(gòu)造器//隱藏//super()//普通代碼和普通屬性的初始化......System.out.println("A02的構(gòu)造器");//(7)}}class C02 {private int n1 = 100;private static int n2 = 200;private void m1() {}private static void m2() {}static {//靜態(tài)代碼塊,只能調(diào)用靜態(tài)成員//System.out.println(n1);錯誤System.out.println(n2);//ok//m1();//錯誤m2();}{//普通代碼塊,可以使用任意成員System.out.println(n1);System.out.println(n2);//okm1();m2();}
}class B02 extends A02 { //private static int n3 = getVal03();static {System.out.println("B02的一個靜態(tài)代碼塊..");//(4)}public int n5 = getVal04();{System.out.println("B02的第一個普通代碼塊..");//(9)}public static int getVal03() {System.out.println("getVal03");//(3)return 10;}public int getVal04() {System.out.println("getVal04");//(8)return 10;}//一定要慢慢的去品..public B02() {//構(gòu)造器//隱藏了//super()//普通代碼塊和普通屬性的初始化...System.out.println("B02的構(gòu)造器");//(10)// TODO Auto-generated constructor stub}
}
7. final細(xì)節(jié)補充
7.1 final的修飾屬性的賦值
package com.hspedu.final_;public class FinalDetail01 {public static void main(String[] args) {CC cc = new CC();new EE().cal();}
}class AA {/*1. 定義時:如 public final double TAX_RATE=0.08;2. 在構(gòu)造器中3. 在代碼塊中*/public final double TAX_RATE = 0.08;//1.定義時賦值public final double TAX_RATE2 ;public final double TAX_RATE3 ;public AA() {//構(gòu)造器中賦值TAX_RATE2 = 1.1;}{//在代碼塊賦值TAX_RATE3 = 8.8;}
}class BB {/*如果final修飾的屬性是靜態(tài)的,則初始化的位置只能是1 定義時 2 在靜態(tài)代碼塊 不能在構(gòu)造器中賦值。*/public static final double TAX_RATE = 99.9;public static final double TAX_RATE2 ;static {TAX_RATE2 = 3.3;}}//final類不能繼承,但是可以實例化對象
final class CC { }//如果類不是final類,但是含有final方法,則該方法雖然不能重寫,但是可以被繼承
//即,仍然遵守繼承的機制.
class DD {public final void cal() {System.out.println("cal()方法");}
}
class EE extends DD { }
7.1 權(quán)限修飾符和static修飾的常量不會導(dǎo)致類加載
package com.hspedu.final_;public class FinalDetail02 {public static void main(String[] args) {System.out.println(BBB.num); //10000//不會執(zhí)行靜態(tài)代碼塊,因為final和static修飾的常量不會導(dǎo)致類加載//包裝類,String 是final類,不能被繼承}
}//final 和 static 往往搭配使用,效率更高,不會導(dǎo)致類加載.底層編譯器做了優(yōu)化處理
class BBB {public final static int num = 10000;static {System.out.println("BBB 靜態(tài)代碼塊被執(zhí)行");}
}
final class AAA{//一般來說,如果一個類已經(jīng)是final類了,就沒有必要再將方法修飾成final方法//public final void cry() {}
}