后端学习 - Java基础
文章目錄
- 一 基礎概念
- 1 有關Java
- 2 JVM / JDK / JRE
- 3 與C++的聯系和區別
- 二 Java語法
- 1 各類型數據占用空間大小
- 2 可變長參數
- 3 靜態方法與實例方法
- 4 重載和重寫
- 5 泛型
- 6 == 和 equals() 的區別
- 7 hashCode() 方法
- 8 包裝類型
- 9 final 關鍵字
- 10 Java的參數傳遞機制
- 11 String 的內存情況
- 12 lambda 表達式
- 三 Java的面向對象
- 1 面向過程與面向對象
- 2 對象與對象引用
- 3 構造方法
- 4 封裝、繼承、多態
- 5 StringBuffer 與 StringBuilder
- 6 引用拷貝、淺拷貝與深拷貝
- 7 代理模式
- 8 匿名類
- 9 內部類
- 四 異常
- 1 異常分類
- 2 try - catch - finally 結構
- 3 不執行 finally 的特殊情況
- 4 使用 try-with-resources 代替 try-catch-finally
- 五 I/O流
- 1 transient 關鍵字
- 2 通過鍵盤獲取輸入的兩種方法
- 3 I/O流分類
- 4 為什么使用字節流
- 六 反射
- 1 動態語言
- 2 什么是反射
- 3 反射的常用API
- 4 反射的實例
- 5 反射與封裝性并不矛盾
- 6 Class 類
- 7 newInstance()
- 8 反射的應用:動態代理模式
一 基礎概念
1 有關Java
- 編譯型語言會通過編譯器將源代碼一次性翻譯成可被該平臺執行的機器碼。一般情況下,編譯語言的執行速度比較快,開發效率比較低。
- 解釋型語言會通過解釋器一句一句的將代碼解釋(interpret)為機器代碼后再執行。解釋型語言開發效率比較快,執行速度比較慢。
- Java是編譯與解釋并存的語言。由 Java 編寫的程序需要先經過編譯步驟,生成字節碼(.class 文件),這種字節碼必須由 Java 解釋器來解釋執行。字節碼對應.class文件,它是面向JVM而非特定系統的,具有良好的可移植性。
2 JVM / JDK / JRE
- JVM(Java virtual machine):運行 Java 字節碼(.class格式文件)的虛擬機,針對不同系統有不同的實現。JVM是一種規范,滿足規范的虛擬機都可稱為JVM。
- JDK(Java development kit):功能齊全的 Java SDK。擁有 JRE 所擁有的一切,還有編譯器(javac)和工具(如 javadoc 和 jdb)。它能夠創建和編譯程序。
- JRE(Java runtime environment):Java 運行時環境。它是運行已編譯 Java 程序所需的所有內容的集合,包括 Java 虛擬機(JVM),Java 類庫,java 命令和其他的一些基礎構件。但是不能用于創建新程序。
總之,JDK 包含 JRE 包含 JVM。
3 與C++的聯系和區別
- 都是面向對象的語言,支持封裝、繼承、多態;
- Java 不提供指針來直接訪問內存,程序內存更加安全;
- Java 的類是單繼承的(接口支持多重繼承),C++ 支持多重繼承;
- Java 有自動內存管理垃圾回收機制;
- C ++同時支持方法重載和操作符重載,但是 Java 只支持方法重載。
二 Java語法
1 各類型數據占用空間大小
Java中比較特殊的是char類型占用2字節(16bits)
2 可變長參數
下面的方法可以接受0或多個參數,可變長的形式參數只能放在參數列表的末尾,在實現時會被視為數組。
public static void printVariable(String... args) {for (String s : args) {System.out.println(s);} }3 靜態方法與實例方法
- 靜態方法屬于類,因此靜態方法可以不創建實例使用。最好使用 類名.方法名 的方式調用。
- 同樣的,靜態方法只能訪問別的靜態方法與靜態成員變量,不能訪問非靜態成員。
- static 方法不能被重寫(不能稱之為重寫)。
4 重載和重寫
- 重載:相同的方法名,不同的參數列表。可以發生在一個類中,也可以發生在父類和子類間。重載就是同一個類中多個同名方法根據不同的傳參來執行不同的邏輯處理。重載發生在編譯時。
- 重寫:相同的方法名,相同的參數列表。發生在父類和子類間,本質上是子類覆蓋了父類的方法。重寫發生在運行時。
重寫要實現的目的是,父類方法能完成的事,子類重寫后不能完成得更差。具體指的是:拋出異常的類型更小或相等,訪問權限更大或相等,返回值的類型更小或相等(如果方法的返回類型是 void 和基本數據類型,則返回值重寫時不可修改。但是如果方法的返回值是引用類型,重寫時可以返回該引用類型的子類)。
另外,static 方法不能被重寫(不能稱之為重寫)。
5 泛型
- 泛型的本質是參數化類型,即數據類型被指定為一個參數。
- 如果實例化泛型類時,沒有指定具體的類型,則認為此泛型的類型為 Object(不推薦)。
- 繼承泛型類時,只需在 extends 后的父類后指明泛型類型即可(public class SubOrder extends Order<String>)。如果不指明,則當前類仍然沿用泛型(public class ArrayList<E> extends AbstractList<E>)。
- 泛型類的構造器在聲明時不需要加泛型符號,但調用構造器時需要指明類型。
- 顯然,靜態方法中不能使用類的泛型。
- 不能使用 new T[capacity] 創建泛型數組,因為在編譯時 T 不是一個具體的類,無法通過編譯。要先創建 Object 數組再強轉:(T[]) new Object[capacity]。
- 泛型方法并不是“使用”了泛型的方法,而是“定義”了新泛型的方法。泛型方法可以用 static 修飾。
- 類A是類B的父類,但G<A> 和G<B>二者不具備子父類關系,二者是并列關系,共同的父類是 G<?>;類A是類B的父類,A<G> 是 B<G> 的父類。(子父類的判斷不看泛型,只看括號外的類型)。
- 通配符的限制符號:G<? extends A> 可以放A和A的子類;G<? super A>可以放A和A的父類。
- Java 的泛型是偽泛型,因為 Java 在運行期間,所有的泛型信息都會被擦掉(類型擦除) 。
HashMap 中泛型的使用(泛型嵌套):
public void test3(){//Map<String,Integer> map = new HashMap<String,Integer>();//jdk7新特性:類型推斷Map<String,Integer> map = new HashMap<>();map.put("Tom",87);map.put("Jerry",87);map.put("Jack",67);//map.put(123,"ABC");//泛型的嵌套Set<Map.Entry<String,Integer>> entry = map.entrySet();Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();while(iterator.hasNext()){Map.Entry<String, Integer> e = iterator.next(); // Entry是Map的內部類String key = e.getKey();Integer value = e.getValue();System.out.println(key + "----" + value);}}6 == 和 equals() 的區別
- 對于基本數據類型,只能用 == 比較。
- 對于引用數據類型, == 用于比較內存地址; equals() 如果未被重寫,也是比較內存地址,重寫后按照指定規則判斷兩個對象是否相等。
7 hashCode() 方法
- 重寫 equals() 方法時,必須同時重寫 hashCode() 方法。
- 兩個對象的 hashCode 值相等并不代表兩個對象就相等(哈希碰撞)。兩個對象相等則 hashCode 必相等。
- 兩個對象的比較,首先比較 hashCode() 的返回值是否相等,如果不相等直接認為兩個對象不相等,如果相等則繼續調用 equals() 方法,返回 True 時視為兩個對象相等。
- 如果重寫 equals() 時沒有重寫 hashCode() 方法的話,可能會導致 equals 方法判斷是相等的兩個對象,hashCode 值卻不相等。
- hashCode() 存在的意義是,減少 equals() 的調用,提高執行速度。
8 包裝類型
- 包裝類型的比較必須用 equals() 。
- 包裝類型不賦值就是 Null ,而基本類型有默認值且不是 Null。
- 基本數據類型直接存放在 Java 虛擬機棧中的局部變量表中,而包裝類型屬于對象類型,存在于堆中。相比于對象類型, 基本數據類型占用的空間非常小。 補充:局部變量表主要存放了編譯期可知的基本數據類型 、對象引用(reference 類型,它不同于對象本身,可能是一個指向對象起始地址的引用指針,也可能是指向一個代表對象的句柄或其他與此對象相關的位置)。
- Java 基本類型的包裝類的大部分都實現了常量池技術。 Byte,Short,Integer,Long 這 4 種包裝類默認創建了數值 [-128,127] 的相應類型的緩存數據,Character 創建了數值在 [0,127] 范圍的緩存數據,Boolean 直接返回 True or False。Float,Double 并沒有實現常量池技術。
- 裝箱與拆箱:裝箱其實就是調用了 包裝類的valueOf()方法,拆箱其實就是調用了 xxxValue()方法。
9 final 關鍵字
被 final 關鍵字修飾的類不能被繼承,修飾的方法不能被重寫,修飾的變量是基本數據類型則值不能改變,修飾的變量是引用類型則不能再指向其他對象。
10 Java的參數傳遞機制
Java只存在值傳遞,如果向方法傳遞引用類型,則在方法中產生引用類型的堆中的地址的拷貝。
public class Person {private String name;// 省略構造函數、Getter&Setter方法 }public static void main(String[] args) {Person xiaoZhang = new Person("小張");Person xiaoLi = new Person("小李");swap(xiaoZhang, xiaoLi);System.out.println("xiaoZhang:" + xiaoZhang.getName());System.out.println("xiaoLi:" + xiaoLi.getName()); }public static void swap(Person person1, Person person2) {Person temp = person1;person1 = person2;person2 = temp;System.out.println("person1:" + person1.getName());System.out.println("person2:" + person2.getName()); }輸出: person1:小李 person2:小張 xiaoZhang:小張 xiaoLi:小李是因為 swap 方法的參數 person1 和 person2 只是拷貝的實參 xiaoZhang 和 xiaoLi 的地址。因此, person1 和 person2 的互換只是拷貝的兩個地址的互換,不會影響到實參 xiaoZhang 和 xiaoLi 。
另附自己驗證的代碼:
11 String 的內存情況
str_instance.intern() 將字符串 str 放到常量池中
12 lambda 表達式
JDK 1.8 之后的特性。本質是函數式接口(僅包含一個方法的接口,接口上使用 @FunctionalInterface 注解)的實例。
三 Java的面向對象
1 面向過程與面向對象
- 面向過程 :面向過程性能比面向對象高。 因為類調用時需要實例化,開銷比較大,比較消耗資源,所以當性能是最重要的考量因素的時候,比如單片機、嵌入式開發、Linux/Unix 等一般采用面向過程開發。但是,面向過程沒有面向對象易維護、易復用、易擴展。
- 面向對象 :面向對象易維護、易復用、易擴展。 因為面向對象有封裝、繼承、多態性的特性,所以可以設計出低耦合的系統,使系統更加靈活、更加易于維護。但是,面向對象性能比面向過程低。
2 對象與對象引用
- 使用 new 創建對象實例(對象實例在堆內存中),對象引用指向對象實例(對象引用存放在棧內存中)。
- 對象的相等,比的是內存中存放的內容是否相等。而引用相等,比較的是他們指向的內存地址是否相等。
3 構造方法
- 一個類即使沒有聲明構造方法也會有默認的不帶參數的構造方法。如果我們自己添加了類的構造方法(無論是否有參),Java 就不會再添加默認的無參數的構造方法了。
- 如果重載了有參的構造方法,要把無參的構造方法也寫出來(無論是否用到),可以幫助我們在創建對象的時候少踩坑。
- 構造方法不能重寫,但是可以重載。
- 如果子類構造方法沒有顯式地調用 super 構造器,則默認調用 super()。
- 通過子類構造器創建對象時,一定會直接或間接地調用父類的構造器,如此直到調用了 Object 類的構造器。但實際上只創建了一個子類的對象。
4 封裝、繼承、多態
- 封裝:封裝是指把一個對象的狀態信息(也就是屬性)隱藏在對象內部,不允許外部對象直接訪問對象的內部信息。但是可以提供一些可以被外界訪問的方法來操作屬性。
- 繼承:繼承是使用已存在的類的定義作為基礎建立新類的技術,新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。子類擁有父類對象所有的屬性和方法(包括私有屬性和私有方法),但是父類中的私有屬性和方法子類是無法訪問,只是擁有。
- 多態:編譯時類型和運行時類型不一致(編譯時看左邊,運行時看右邊),具體表現為父類的引用指向子類的實例。引用類型變量發出的方法調用的到底是哪個類中的方法,必須在程序運行期間才能確定;多態不能調用“只在子類存在但在父類不存在”的方法,盡管內存中加載了子類特有的屬性和方法,想要調用需要向下轉型。多態情況下,父類的方法稱為虛(擬)方法,調用方法的過程稱為動態綁定。
5 StringBuffer 與 StringBuilder
- StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類。
- StringBuffer 對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。StringBuilder 并沒有對方法進行加同步鎖,所以是非線程安全的。
- 性能:StringBuilder > StringBuffer > String;安全性:String > StringBuffer > StringBuilder
- 選擇:操作少量的數據適用 String;單線程操作字符串緩沖區下操作大量數據適用 StringBuilder;多線程操作字符串緩沖區下操作大量數據適用 StringBuffer。
6 引用拷貝、淺拷貝與深拷貝
- 引用拷貝:創建新的對象引用,指向原來的對象。
- 淺拷貝:淺拷貝會在堆上創建一個新的對象(區別于引用拷貝的一點),不過,如果原對象內部的屬性是引用類型的話,淺拷貝會直接復制內部對象的引用地址,也就是說拷貝對象和原對象共用同一個內部對象。
- 深拷貝 :深拷貝會完全復制整個對象,包括這個對象所包含的內部對象。
7 代理模式
靜態代理
- 靜態代理在編譯時就將接口、實現類、代理類這些都變成了一個個實際的 class 文件。通過代理類屏蔽對目標對象的訪問,并且可以在目標方法執行前后做一些自己想做的事情。
- 靜態代理的實現步驟:定義一個接口及其實現類; 創建一個代理類同樣實現這個接口,將目標對象注入進代理類(使其成為代理類的成員變量);然后在代理類的對應方法調用目標類中的對應方法。
- 靜態代理中,對目標對象的每個方法的增強都是手動完成的,非常不靈活(比如接口一旦新增加方法,目標對象和代理對象都要進行修改且麻煩(需要對每個目標類都單獨寫一個代理類)。
JDK動態代理(反射的應用)
- 動態代理在運行時動態生成類字節碼,并加載到 JVM 中的。
- 動態代理更加靈活,不需要必須實現接口,可以直接代理實現類,并且可以不需要針對每個目標類都創建一個代理類。“一個代理類,完成全部的代理功能”。
使用實例:
8 匿名類
9 內部類
內部類的分類、成員內部類的使用:
/** 類的內部成員之五:內部類* 1. Java中允許將一個類A聲明在另一個類B中,則類A就是內部類,類B稱為外部類* * 2.內部類的分類:成員內部類(靜態、非靜態) vs 局部內部類(方法內、代碼塊內、構造器內)* * 3.成員內部類:* 一方面,作為外部類的成員:* >調用外部類的結構* >可以被static修飾* >可以被4種不同的權限修飾* * 另一方面,作為一個類:* > 類內可以定義屬性、方法、構造器等* > 可以被final修飾,表示此類不能被繼承。言外之意,不使用final,就可以被繼承* > 可以被abstract修飾*/ public class InnerClassTest {public static void main(String[] args) {//創建Dog實例(靜態的成員內部類):Person.Dog dog = new Person.Dog();dog.show();//創建Bird實例(非靜態的成員內部類): // Person.Bird bird = new Person.Bird();//錯誤Person p = new Person();Person.Bird bird = p.new Bird();bird.sing();System.out.println();bird.display("黃鸝");} }class Person{String name = "小明";int age;public void eat(){System.out.println("人:吃飯");}// 靜態成員內部類static class Dog{String name;int age;public void show(){System.out.println("卡拉是條狗");//eat(); 錯誤,只能調用靜態方法}}// 非靜態成員內部類class Bird{String name = "杜鵑";public Bird(){}public void sing(){System.out.println("我是一只小小鳥");Person.this.eat(); // 調用外部類的非靜態屬性,需要加 Person.thisSystem.out.println(age);}public void display(String name){System.out.println(name); // 方法的形參System.out.println(this.name); // 內部類的屬性System.out.println(Person.this.name); // 外部類的屬性,需要加 Person.this}}public void method(){//局部內部類 - 成員方法內定義class AA{}}{//局部內部類 - 代碼塊內定義class BB{}}public Person(){//局部內部類 - 構造方法內定義class CC{}} }局部內部類的使用:
package com.atguigu.java2;public class InnerClassTest1 { //返回一個實現了Comparable接口的類的對象public Comparable getComparable(){//創建一個實現了Comparable接口的類:局部內部類//方式一,使用內部類:class MyComparable implements Comparable{@Overridepublic int compareTo(Object o) {return 0;}}return new MyComparable();//方式二,使用匿名類:return new Comparable(){@Overridepublic int compareTo(Object o) {return 0;}};} }四 異常
1 異常分類
- Checked exception 必須處理,Unchecked exception可以不處理。
- 在編譯過程中,如果受檢查異常沒有被 catch/throw 處理的話,就沒辦法通過編譯 。
- 除了 RuntimeException 及其子類以外,其他的Exception類及其子類都屬于受檢查異常 。
2 try - catch - finally 結構
- try: 用于捕獲異常。其后可接零個或多個 catch 塊,如果沒有 catch 塊,則必須跟一個 finally 塊。
- catch塊: 用于處理 try 捕獲到的異常。
- finally 塊: 無論是否捕獲或處理異常,finally 塊里的語句都會被執行。當在 try 塊或 catch 塊中遇到 return 語句時,finally 語句塊將在方法返回之前被執行。當 try 語句和 finally 語句中都有 return 語句時,在方法返回之前,finally 語句的內容將被執行,并且 finally 語句的返回值將會覆蓋原始的返回值。
3 不執行 finally 的特殊情況
- 在 try 或 finally塊中用了 System.exit(int)退出程序。但如果 System.exit(int) 在異常語句之后,finally 還是會被執行。
- 程序所在的線程死亡。
- 關閉 CPU。
4 使用 try-with-resources 代替 try-catch-finally
具體的做法是,在 try 關鍵字后增加括號,在其中創建資源對象(任何實現 java.lang.AutoCloseable或者 java.io.Closeable 的對象),這樣使得 catch 或 finally 塊必須在資源關閉后執行,而不必顯式關閉。
try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {int b;while ((b = bin.read()) != -1) {bout.write(b);}}catch (IOException e) {e.printStackTrace();}五 I/O流
1 transient 關鍵字
- 作用是阻止實例中那些用此關鍵字修飾的的變量序列化;當對象被反序列化時,被 transient 修飾的變量值不會被持久化和恢復。
- transient 只能修飾變量,不能修飾類和方法。
- transient 修飾的變量,在反序列化后變量值將會被置成類型的默認值。例如,如果是修飾 int 類型,那么反序列后結果就是 0。
- static 變量因為不屬于任何對象(Object),所以無論有沒有 transient 關鍵字修飾,均不會被序列化。
2 通過鍵盤獲取輸入的兩種方法
- Scanner
- BufferedReader
3 I/O流分類
- 按照流的流向分,可以分為輸入流和輸出流;
- 按照操作單元劃分,可以劃分為字節流(1byte=8bit)和字符流(2byte=16bit,因為Java的字符占兩個字節);
- 按照流的角色劃分為節點流和處理流。
4 為什么使用字節流
字符流是由 Java 虛擬機將字節轉換得到的,這個過程還算是非常耗時。并且,如果不知道編碼類型,很容易出現亂碼問題。
六 反射
1 動態語言
- 動態語言指運行時可以改變其結構的語言:例如新的函數、對象、甚至代碼可以被引進,已有的函數可以被刪除或是其他結構上的變化。通俗點說就是在運行時代碼可以根據某些條件改變自身結構。
- 反射機制使得Java成為了“準動態語言”。加載完類之后,在堆內存的方法區中就產生了一個Class類型的對象(一個類只有一個Class對象),這個對象就包含了完整的類的結構信息。
2 什么是反射
- Java反射就是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;并且能改變它的屬性。
- 反射機制允許程序在運行時取得任何一個已知名稱的class的內部信息,包括包括其modifiers(修飾符),fields(屬性),methods(方法)等,并可于運行時改變fields內容或調用methods。
- 編譯時無法確定實例化哪個類的對象,使用反射。
3 反射的常用API
- java.lang.Class: 代表一個類(區別于關鍵字 class)
- java.lang.reflect.Method: 代表類的方法
- java.lang.reflect.Field: 代表類的成員變量
- java.lang.reflect.Constructor: 代表類的構造器
4 反射的實例
對于類:
package com.ys.reflex; public class Person {//私有屬性private String name = "Tom";//公有屬性public int age = 18;//構造方法public Person() {}//私有方法private void say(){System.out.println("private say()...");}//公有方法public void work(){System.out.println("public work()...");} }獲取類名的三種方式:
Class 的實例就對應著一個運行時類,獲取 Class 實例不能使用 new,而應該通過具體的實例獲得!
Class 類具有如下的方法:
- getName():獲得類的完整名字。
- getFields():獲得類的public類型的屬性。
- getDeclaredFields():獲得類的所有屬性。包括private 聲明的和繼承類
- getMethods():獲得類的public類型的方法。
- getDeclaredMethods():獲得類的所有方法。包括private 聲明的和繼承類
- getMethod(String name, Class[] parameterTypes):獲得類的特定方法,name參數指定方法的名字,parameterTypes 參數指定方法的參數類型。
- getConstructors():獲得類的public類型的構造方法。
- getConstructor(Class[] parameterTypes):獲得類的特定構造方法,parameterTypes 參數指定構造方法的參數類型。
- newInstance():通過類的不帶參數的構造方法創建這個類的一個對象。
調用以上方法:
public void test2() throws Exception{Class clazz = Person.class;//1.通過反射,創建Person類的對象Constructor cons = clazz.getConstructor(String.class,int.class);Object obj = cons.newInstance("Tom", 12);Person p = (Person) obj;System.out.println(p.toString());//2.通過反射,調用對象指定的屬性、方法//調用屬性Field age = clazz.getDeclaredField("age");age.set(p,10);//調用方法// 參數1 :指明獲取的方法的名稱 參數2:指明獲取的方法的形參列表Method show = clazz.getDeclaredMethod("show"); // 參數1:方法的調用者 參數2:給方法形參賦值的實參 返回值:對應類中調用的方法的返回值show.invoke(p); //調用私有的構造器Constructor cons1 = clazz.getDeclaredConstructor(String.class);cons1.setAccessible(true);Person p1 = (Person) cons1.newInstance("Jerry");//調用私有的屬性Field name = clazz.getDeclaredField("name");name.setAccessible(true);name.set(p1,"HanMeimei");//調用私有的方法Method showNation = clazz.getDeclaredMethod("showNation", String.class);showNation.setAccessible(true);String nation = (String) showNation.invoke(p1,"中國");//相當于String nation = p1.showNation("中國")// 調用靜態方法// private static void showDesc()Method showDesc = clazz.getDeclaredMethod("showDesc");showDesc.setAccessible(true);//Object returnVal = showDesc.invoke(Person.class); // 調用者為類,但這么寫多余,因為在獲取 showDesc 時已經知道是靜態方法Object returnVal = showDesc.invoke(null); // 可以}5 反射與封裝性并不矛盾
- 封裝性:建議調用權限可達的方法;
- 反射:忽略封裝性的建議,能調用封裝性不推薦的方法。
6 Class 類
- Class 的實例就對應著一個運行時類!獲取 Class 實例不能使用 new,而應該通過具體的實例獲得。
對應關系:
| Class實例 | 實例運行時類 |
| 實例 |
7 newInstance()
- newInstance():調用此方法,創建對應的運行時類的對象。內部調用了運行時類的空參的構造器。帶參的構造器不夠“動態”!
- 要想此方法正常的創建運行時類的對象,要求:
- 運行時類必須提供空參的構造器;
- 空參的構造器的訪問權限得夠。通常,設置為 public 。 - 在 javabean 中要求提供一個 public 的空參構造器。原因:
- 便于通過反射,創建運行時類的對象;
- 便于子類繼承此運行時類時,默認調用 super() 時,保證父類有此構造器。
8 反射的應用:動態代理模式
使用實例:
總結
以上是生活随笔為你收集整理的后端学习 - Java基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构 - 最小堆最大堆
- 下一篇: 红旗 H9 + 不息版上市:车身拥有特殊