刪除連結串列中重複的節點 java 遞迴實現
阿新 • • 發佈:2021-01-03
前言
文章內容輸出來源:拉勾教育Java就業訓練營
上一階段內容,java 網路程式設計
反射機制
基本概念
- 通常情況下編寫程式碼都是固定的,無論執行多少次執行的結果也是固定的,在某些特殊場合中編寫程式碼時不確定要建立什麼型別的物件,也不確定要呼叫什麼樣的方法,這些都希望通過執行時傳遞的引數來決定,該機制叫做動態程式設計技術,也就是反射機制。
- 通俗來說,反射機制就是用於動態建立物件並且動態呼叫方法的機制。
- 目前主流的框架底層都是採用反射機制實現的。
- 如:
Person p = new Person(); - 表示宣告Person型別的引用指向Person型別的物件
Class類
基本概念
- java.lang.Class類的例項可以用於描述Java應用程式中的類和介面,也就是一種資料型別。
- 該類沒有公共構造方法,該類的例項由Java虛擬機器和類載入器自動構造完成,本質上就是載入到記憶體中的執行時類。
獲取Class物件的方式
- 使用資料型別.class的方式可以獲取對應型別的Class物件(掌握)。
- 使用引用/物件.getClass()的方式可以獲取對應型別的Class物件。
- 使用包裝類.TYPE的方式可以獲取對應基本資料型別的Class物件。
- 使用Class.forName()的方式來獲取引數指定型別的Class物件(掌握)。
- 使用類載入器ClassLoader的方式獲取指定型別的Class物件。
public static void main(String[] args) throws ClassNotFoundException {
// 1.使用資料型別.class的方式可以獲取對應型別的Class物件
Class c1 = String.class;
System.out.println("c1 = " + c1); // 自動呼叫toString方法 class java.lang.String
c1 = int.class ;
System.out.println("c1 = " + c1); // int
c1 = void.class;
System.out.println("c1 = " + c1); // void
System.out.println("---------------------------------------------------");
// 2.使用物件.getClass()的方式獲取對應的Class物件
String str1 = new String("hello");
c1 = str1.getClass();
System.out.println("c1 = " + c1); // class java.lang.String
Integer it1 = 20;
c1 = it1.getClass();
System.out.println("c1 = " + c1); // class java.lang.Integer
int num = 5;
//num.getClass(); Error: 基本資料型別的變數不能呼叫方法
System.out.println("---------------------------------------------------");
// 3.使用包裝類.TYPE的方式來獲取對應基本資料型別的Class物件
c1 = Integer.TYPE;
System.out.println("c1 = " + c1); // int
c1 = Integer.class;
System.out.println("c1 = " + c1); // class java.lang.Integer
System.out.println("---------------------------------------------------");
// 4.呼叫Class類中的forName方法來獲取對應的Class物件
//c1 = Class.forName("String"); // Error 要求寫完整的名稱:包名.類名
c1 = Class.forName("java.lang.String");
System.out.println("c1 = " + c1); // class java.lang.String
c1 = Class.forName("java.util.Date");
System.out.println("c1 = " + c1); // class java.util.Date
//c1 = Class.forName("int");
//System.out.println("c1 = " + c1); // 不能獲取基本資料型別的Class物件
System.out.println("---------------------------------------------------");
// 5.使用類載入器的方式來獲取Class物件
ClassLoader classLoader = ClassTest.class.getClassLoader();
System.out.println("classLoader = " + classLoader); // null
c1 = classLoader.loadClass("java.lang.String");
System.out.println("c1 = " + c1); // class java.lang.String
}
輸出>>>
c1 = class java.lang.String
c1 = int
c1 = void
---------------------------------------------------
c1 = class java.lang.String
c1 = class java.lang.Integer
---------------------------------------------------
c1 = int
c1 = class java.lang.Integer
---------------------------------------------------
c1 = class java.lang.String
c1 = class java.util.Date
---------------------------------------------------
classLoader = jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
c1 = class java.lang.String
常用的方法
方法宣告 | 功能介紹 |
---|---|
static Class<?> forName(String className) | 用於獲取引數指定型別對應的Class物件並返回 |
T newInstance() | 用於建立該Class物件所表示類的新例項 |
Constructor類
基本概念
- java.lang.reflect.Constructor類主要用於描述獲取到的構造方法資訊
Class類的常用方法
方法宣告 | 功能介紹 |
---|---|
Constructor getConstructor(Class<?>… parameterTypes) | 用於獲取此Class物件所表示型別中引數指定的公共構造方法 |
Constructor<?>[] getConstructors() | 用於獲取此Class物件所表示型別中所有的公共構造方法 |
Constructor類的常用方法
方法宣告 | 功能介紹 |
---|---|
T newInstance(Object… initargs) | 使用此Constructor物件描述的構造方法來構造Class物件代表型別的新例項 |
int getModifiers() | 獲取方法的訪問修飾符 |
String getName() | 獲取方法的名稱 |
Class<?>[] getParameterTypes() | 獲取方法所有引數的型別 |
配置檔案
實體類
public class Person {
private String name;
//public String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) throws IOException {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
測試類
public static void main(String[] args) throws Exception {
// 1.使用原始方式以無參形式構造Person型別的物件並列印
Person p1 = new Person();
System.out.println("無參方式建立的物件是:" + p1); // null 0
System.out.println("---------------------------------------------------");
// 2.使用反射機制以無參形式構造Person型別的物件並列印
// 建立物件的型別可以從鍵盤輸入
//System.out.println("請輸入要建立物件的型別:");
//Scanner sc = new Scanner(System.in);
//String str1 = sc.next();
//Class c1 = Class.forName("com.task20.Person");
// 建立物件的型別可以從配置檔案中讀取
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:/a.txt")));
String str1 = br.readLine();
Class c1 = Class.forName(str1);
//System.out.println("無參方式建立的物件是:" + c1.newInstance()); // null 0
// 獲取Class物件對應類中的無參構造方法,也就是Person類中的無參構造方法
Constructor constructor = c1.getConstructor();
// 使用獲取到的無參構造方法來構造對應型別的物件,也就是Person型別的物件
System.out.println("無參方式建立的物件是:" + constructor.newInstance());
//sc.close();
br.close();
System.out.println("---------------------------------------------------");
// 3.使用原始方式以有參方式構造Person型別的物件並列印
Person p2 = new Person("zhangfei", 30);
System.out.println("有參方式構造的物件是:" + p2); // zhangfei 30
System.out.println("---------------------------------------------------");
// 4.使用反射機制以有參方式構造Person型別的物件並列印
// 獲取Class物件對應類中的有參構造方法,也就是Person類中的有參構造方法
Constructor constructor1 = c1.getConstructor(String.class, int.class);
// 使用獲取到的有參構造方法來構造對應型別的物件,也就是Person型別的物件
// newInstance方法中的實參是用於給有參構造方法的形參進行初始化的,也就是給name和age進行初始化的
System.out.println("有參方式構造的物件是:" + constructor1.newInstance("zhangfei", 30)); // zhangfei 30
System.out.println("---------------------------------------------------");
// 5.使用反射機制獲取Person類中所有的公共構造方法並列印
Constructor[] constructors = c1.getConstructors();
for (Constructor ct : constructors) {
System.out.println("構造方法的訪問修飾符是:" + ct.getModifiers());
System.out.println("構造方法的方法名稱是:" + ct.getName());
Class[] parameterTypes = ct.getParameterTypes();
System.out.print("構造方法的所有引數型別是:");
for (Class cs : parameterTypes) {
System.out.print(cs + " ");
}
System.out.println();
System.out.println("-------------------------------------------------");
}
}
輸出結果>>>
無參方式建立的物件是:Person{name='null', age=0}
---------------------------------------------------
無參方式建立的物件是:TestPerson{name='null', age=0}
---------------------------------------------------
有參方式構造的物件是:Person{name='zhangfei', age=30}
---------------------------------------------------
有參方式構造的物件是:TestPerson{name='zhangfei', age=30}
---------------------------------------------------
構造方法的訪問修飾符是:1
構造方法的方法名稱是:com.task20.test.TestPerson
構造方法的所有引數型別是:
-------------------------------------------------
構造方法的訪問修飾符是:1
構造方法的方法名稱是:com.task20.test.TestPerson
構造方法的所有引數型別是:class java.lang.String int
-------------------------------------------------
Field類
基本概念
- java.lang.reflect.Field類主要用於描述獲取到的單個成員變數資訊。
Class類的常用方法
方法宣告 | 功能介紹 |
---|---|
Field getDeclaredField(String name) | 用於獲取此Class物件所表示類中引數指定的單個成員變數資訊 |
Field[] getDeclaredFields() | 用於獲取此Class物件所表示類中所有成員變數資訊 |
Field類的常用方法
方法宣告 | 功能介紹 |
---|---|
Object get(Object obj) | 獲取引數物件obj中此Field物件所表示成員變數的數值 |
void set(Object obj, Object value) | 將引數物件obj中此Field物件表示成員變數的數值修改為引數value的數值 |
void setAccessible(boolean flag) | 當實參傳遞true時,則反射物件在使用時應該取消 Java 語言訪問檢查 |
int getModifiers() | 獲取成員變數的訪問修飾符 |
Class<?> getType() | 獲取成員變數的資料型別 |
String getName() | 獲取成員變數的名稱 |
Method類
基本概念
java.lang.reflect.Method類主要用於描述獲取到的單個成員方法資訊。
Class類的常用方法
方法宣告 | 功能介紹 |
---|---|
Method getMethod(String name, Class<?>… parameterTypes) | 用於獲取該Class物件表示類中名字為name引數為parameterTypes的指定公共成員方法 |
Method[] getMethods() | 用於獲取該Class物件表示類中所有公共成員方法 |
測試類
public static void main(String[] args) throws Exception {
// 1.使用原始方式以無參形式構造Person型別的物件並列印
Person p1 = new Person();
System.out.println("無參方式建立的物件是:" + p1); // null 0
System.out.println("---------------------------------------------------");
// 2.使用反射機制以無參形式構造Person型別的物件並列印
// 建立物件的型別可以從鍵盤輸入
//System.out.println("請輸入要建立物件的型別:");
//Scanner sc = new Scanner(System.in);
//String str1 = sc.next();
//Class c1 = Class.forName("com.lagou.task20.Person");
// 建立物件的型別可以從配置檔案中讀取
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:/a.txt")));
String str1 = br.readLine();
Class c1 = Class.forName(str1);
//System.out.println("無參方式建立的物件是:" + c1.newInstance()); // null 0
// 獲取Class物件對應類中的無參構造方法,也就是Person類中的無參構造方法
Constructor constructor = c1.getConstructor();
// 使用獲取到的無參構造方法來構造對應型別的物件,也就是Person型別的物件
System.out.println("無參方式建立的物件是:" + constructor.newInstance());
//sc.close();
br.close();
System.out.println("---------------------------------------------------");
// 3.使用原始方式以有參方式構造Person型別的物件並列印
Person p2 = new Person("zhangfei", 30);
System.out.println("有參方式構造的物件是:" + p2); // zhangfei 30
System.out.println("---------------------------------------------------");
// 4.使用反射機制以有參方式構造Person型別的物件並列印
// 獲取Class物件對應類中的有參構造方法,也就是Person類中的有參構造方法
Constructor constructor1 = c1.getConstructor(String.class, int.class);
// 使用獲取到的有參構造方法來構造對應型別的物件,也就是Person型別的物件
// newInstance方法中的實參是用於給有參構造方法的形參進行初始化的,也就是給name和age進行初始化的
System.out.println("有參方式構造的物件是:" + constructor1.newInstance("zhangfei", 30)); // zhangfei 30
System.out.println("---------------------------------------------------");
// 5.使用反射機制獲取Person類中所有的公共構造方法並列印
Constructor[] constructors = c1.getConstructors();
for (Constructor ct : constructors) {
System.out.println("構造方法的訪問修飾符是:" + ct.getModifiers());
System.out.println("構造方法的方法名稱是:" + ct.getName());
Class[] parameterTypes = ct.getParameterTypes();
System.out.print("構造方法的所有引數型別是:");
for (Class cs : parameterTypes) {
System.out.print(cs + " ");
}
System.out.println();
System.out.println("-------------------------------------------------");
}
}
輸出結果>>>
無參方式建立的物件是:Person{name='null', age=0}
---------------------------------------------------
無參方式建立的物件是:Person{name='null', age=0}
---------------------------------------------------
有參方式構造的物件是:Person{name='zhangfei', age=30}
---------------------------------------------------
有參方式構造的物件是:Person{name='zhangfei', age=30}
---------------------------------------------------
構造方法的訪問修飾符是:1
構造方法的方法名稱是:com.task20.Person
構造方法的所有引數型別是:
-------------------------------------------------
構造方法的訪問修飾符是:1
構造方法的方法名稱是:com.task20.Person
構造方法的所有引數型別是:class java.lang.String int
-------------------------------------------------
Method類的常用方法
方法宣告 | 功能介紹 |
---|---|
Object invoke(Object obj,Object… args) | 使用物件obj來呼叫此Method物件所表示的成員方法,實參傳遞args |
int getModifiers() | 獲取方法的訪問修飾符 |
Class<?> getReturnType() | 獲取方法的返回值型別 |
String getName() | 獲取方法的名稱 |
Class<?>[] getParameterTypes() | 獲取方法所有引數的型別 |
Class<?>[] getExceptionTypes() | 獲取方法的異常資訊 |
測試類
public static void main(String[] args) throws Exception {
// 1.使用原始方式構造物件並呼叫方法列印結果
Person p1 = new Person("zhangfei", 30);
System.out.println("呼叫方法的返回值是:" + p1.getName()); // zhangfei
System.out.println("------------------------------------------------------");
// 2.使用反射機制構造物件並呼叫方法列印結果
// 2.1 獲取Class物件
Class c1 = Class.forName("com.task20.Person");
// 2.2 根據Class物件來獲取對應的有參構造方法
Constructor constructor = c1.getConstructor(String.class, int.class);
// 2.3 使用有參構造方法構造物件並記錄
Object object = constructor.newInstance("zhangfei", 30);
// 2.4 根據Class物件來獲取對應的成員方法
Method method = c1.getMethod("getName");
// 2.5 使用物件呼叫成員方法進行列印
// 表示使用object物件呼叫method表示的方法,也就是呼叫getName方法來獲取姓名
System.out.println("呼叫方法的返回值是:" + method.invoke(object)); // zhangfei
System.out.println("------------------------------------------------------");
// 3.使用反射機制來獲取類中的所有成員方法並列印
Method[] methods = c1.getMethods();
for (Method mt : methods) {
System.out.println("成員方法的修飾符是:" + mt.getModifiers());
System.out.println("成員方法的返回值型別是:" + mt.getReturnType());
System.out.println("成員方法的名稱是:" + mt.getName());
System.out.println("成員方法形參列表的型別是:");
Class<?>[] parameterTypes = mt.getParameterTypes();
for (Class ct : parameterTypes) {
System.out.print(ct + " ");
}
System.out.println();
System.out.println("成員方法的異常型別列表是:");
Class<?>[] exceptionTypes = mt.getExceptionTypes();
for (Class ct: exceptionTypes) {
System.out.print(ct + " ");
}
System.out.println();
System.out.println("---------------------------------------------------");
}
}
輸出結果>>>
無參方式建立的物件是:Person{name='null', age=0}
---------------------------------------------------
無參方式建立的物件是:Person{name='null', age=0}
---------------------------------------------------
有參方式構造的物件是:Person{name='zhangfei', age=30}
---------------------------------------------------
有參方式構造的物件是:Person{name='zhangfei', age=30}
---------------------------------------------------
構造方法的訪問修飾符是:1
構造方法的方法名稱是:com.task20.Person
構造方法的所有引數型別是:class java.lang.String int
-------------------------------------------------
構造方法的訪問修飾符是:1
構造方法的方法名稱是:com.task20.Person
構造方法的所有引數型別是:
-------------------------------------------------
輸出>>>\
呼叫方法的返回值是:zhangfei
------------------------------------------------------
呼叫方法的返回值是:zhangfei
------------------------------------------------------
成員方法的修飾符是:1
成員方法的返回值型別是:class java.lang.String
成員方法的名稱是:getName
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:1
成員方法的返回值型別是:class java.lang.String
成員方法的名稱是:toString
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:1
成員方法的返回值型別是:void
成員方法的名稱是:setName
成員方法形參列表的型別是:
class java.lang.String
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:1
成員方法的返回值型別是:void
成員方法的名稱是:setAge
成員方法形參列表的型別是:
int
成員方法的異常型別列表是:
class java.io.IOException
---------------------------------------------------
成員方法的修飾符是:1
成員方法的返回值型別是:int
成員方法的名稱是:getAge
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:273
成員方法的返回值型別是:void
成員方法的名稱是:wait
成員方法形參列表的型別是:
long
成員方法的異常型別列表是:
class java.lang.InterruptedException
---------------------------------------------------
成員方法的修飾符是:17
成員方法的返回值型別是:void
成員方法的名稱是:wait
成員方法形參列表的型別是:
long int
成員方法的異常型別列表是:
class java.lang.InterruptedException
---------------------------------------------------
成員方法的修飾符是:17
成員方法的返回值型別是:void
成員方法的名稱是:wait
成員方法形參列表的型別是:
成員方法的異常型別列表是:
class java.lang.InterruptedException
---------------------------------------------------
成員方法的修飾符是:1
成員方法的返回值型別是:boolean
成員方法的名稱是:equals
成員方法形參列表的型別是:
class java.lang.Object
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:257
成員方法的返回值型別是:int
成員方法的名稱是:hashCode
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:273
成員方法的返回值型別是:class java.lang.Class
成員方法的名稱是:getClass
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:273
成員方法的返回值型別是:void
成員方法的名稱是:notify
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
成員方法的修飾符是:273
成員方法的返回值型別是:void
成員方法的名稱是:notifyAll
成員方法形參列表的型別是:
成員方法的異常型別列表是:
---------------------------------------------------
獲取其它結構資訊
方法宣告 | 功能介紹 |
---|---|
Package getPackage() | 獲取所在的包資訊 |
Class<? super T> getSuperclass() | 獲取繼承的父類資訊 |
Class<?>[] getInterfaces() | 獲取實現的所有介面 |
Annotation[] getAnnotations() | 獲取註解資訊 |
Type[] getGenericInterfaces() | 獲取泛型資訊 |
註解測試類
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
介面、父類、等測試類
@MyAnnotation
public class Student<T, E> extends Person implements Comparable<String>, Serializable {
@Override
public int compareTo(String s) {
return 0;
}
}
執行測試類
public static void main(String[] args) throws Exception {
// 獲取Student型別的Class物件
Class c1 = Class.forName("com.task20.Student");
System.out.println("獲取到的包資訊是:" + c1.getPackage());
System.out.println("獲取到的父類資訊是:" + c1.getSuperclass());
System.out.println("-------------------------------------------------");
System.out.println("獲取到的介面資訊是:");
Class[] interfaces = c1.getInterfaces();
for (Class ct : interfaces) {
System.out.print(ct + " ");
}
System.out.println();
System.out.println("-------------------------------------------------");
System.out.println("獲取到的註解資訊是:");
Annotation[] annotations = c1.getAnnotations();
for (Annotation at : annotations) {
System.out.print(at + " ");
}
System.out.println();
System.out.println("-------------------------------------------------");
System.out.println("獲取到的泛型資訊是:");
Type[] genericInterfaces = c1.getGenericInterfaces();
for (Type tt : genericInterfaces) {
System.out.print(tt + " ");
}
System.out.println();
}
輸出結果>>>
獲取到的包資訊是:package com.task20
獲取到的父類資訊是:class com.task20.Person
-------------------------------------------------
獲取到的介面資訊是:
interface java.lang.Comparable interface java.io.Serializable
-------------------------------------------------
獲取到的註解資訊是:
@com.task20.MyAnnotation()
-------------------------------------------------
獲取到的泛型資訊是:
java.lang.Comparable<java.lang.String> interface java.io.Serializable