1. 程式人生 > 其它 >刪除連結串列中重複的節點 java 遞迴實現

刪除連結串列中重複的節點 java 遞迴實現

技術標籤:筆記java反射class

前言

文章內容輸出來源:拉勾教育Java就業訓練營

上一階段內容,java 網路程式設計

反射機制

基本概念

  • 通常情況下編寫程式碼都是固定的,無論執行多少次執行的結果也是固定的,在某些特殊場合中編寫程式碼時不確定要建立什麼型別的物件,也不確定要呼叫什麼樣的方法,這些都希望通過執行時傳遞的引數來決定,該機制叫做動態程式設計技術,也就是反射機制。
  • 通俗來說,反射機制就是用於動態建立物件並且動態呼叫方法的機制。
  • 目前主流的框架底層都是採用反射機制實現的。
  • 如:
    Person p = new Person(); - 表示宣告Person型別的引用指向Person型別的物件
    p.show(); - 表示呼叫Person類中的成員方法show

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