1. 程式人生 > 其它 >Java基礎— —反射

Java基礎— —反射

技術標籤:JAVAjava反射

Java基礎— —反射

本文主要介紹Java反射相關知識。

文章目錄

一、什麼是反射

Java 反射機制在程式執行時,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性。這種 動態的獲取資訊 以及 動態呼叫物件的方法 的功能稱為 java 的反射機制

二、獲取Class物件

一般通過下述三種方法獲取相應的Class物件:

  • Class.forName(“全限定類名”)

  • 類名.class

  • 物件.getClass()

一個類只有一個Class物件。

三、使用Class物件

3.1 獲取類名

我們可以使用Class物件的getName()方法獲取類名。

3.2 獲取成員變數

當建立了一個Class物件後,我們可以使用以下方法獲取成員變數:

方法 宣告解釋
Field getField(String name)獲取指定名稱的公共(public)成員變數。
Field[] getFields()獲取所有的公共(public)成員變數。
Field getDeclaredField(String name)獲取指定名稱的成員變數,不再限制訪問修飾符。
Field[] getDeclaredFields()
獲取所有的成員變數,不再限制訪問修飾符。

當獲取成員變數物件後

  • 可以通過get(Object obj)獲取相應物件的值
  • 也可以通過set(Object obj,Object value)設定相應物件的值。注意,如果修改私有成員變數,需要先忽略訪問許可權修飾符的安全檢查,使用Field的方法setAccessible(true)進行設定。

3.3 獲取構造方法

當建立了一個Class物件後,我們可以使用以下方法獲取構造方法:

方法 說明解釋
Constructor<T> getConstructor(Class<?>... parameterTypes)獲取指定引數型別的公共構造方法
Constructor<?>[] getConstructors()獲取所有的公共構造方法
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)獲取指定引數型別的任意構造方法,不再限制訪問修飾符。
Constructor<?>[] getDeclaredConstructors()獲取所有的構造方法,不再限制訪問修飾符

下面通過例子來解釋什麼是指定引數型別的構造方法:

首先宣告一個Student類:

package com.lee.basic.reflect;

import java.time.LocalDate;

public class Student {
    private String name;               //姓名
    private String studentNumber;      //學號
    private LocalDate birthday;     //出生日期
    private String major;           //專業

    //無參建構函式
    public Student() { }
    
    //全參建構函式
    public Student(String name, String studentNumber, LocalDate birthday, String major) {
        this.name = name;
        this.studentNumber = studentNumber;
        this.birthday = birthday;
        this.major = major;
    }
    
    //有姓名和出生日期的建構函式
    public Student(String name, LocalDate birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    
    //有姓名和學號的建構函式
    public Student(String name, String studentNumber) {
        this.name = name;
        this.studentNumber = studentNumber;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", studentNumber='" + studentNumber + '\'' +
                ", birthday=" + birthday +
                ", major='" + major + '\'' +
                '}';
    }
}

在測試方法中測試通過反射獲取構造方法:

/**
     * 測試通過反射獲取構造方法
     */
@Test
public void testGetConstructor() throws NoSuchMethodException {
    Class<Student> studentClass = Student.class;
    Constructor<Student> constructor = studentClass.getConstructor(String.class, LocalDate.class);
    System.out.println(constructor);
}

結果:

在這裡插入圖片描述

由於構造方法名都是與類名相同,為了區分不同的構造方法,需要指定引數型別,就是指定要獲取的構造方法的引數型別。

當我們獲取了構造方法後,可以通過構造方法物件的newInstance()建立相應的類物件,引數即為類物件建立時需要傳遞的引數值。

T newInstance(Object... initargs)  

測試方法:

/**
     * 測試通過反射獲取構造方法
     */
@Test
public void testGetConstructor() throws Exception {
    Class<Student> studentClass = Student.class;
    //獲取構造方法物件
    Constructor<Student> constructor = studentClass.getConstructor(String.class, LocalDate.class);
    System.out.println(constructor);
    //構造學生物件
    Student student = constructor.newInstance("張三", LocalDate.of(2000, 12, 2));
    System.out.println(student);
}

結果:

在這裡插入圖片描述

3.4 獲取成員方法

當建立了一個Class物件後,我們可以使用以下方法獲取成員方法:

方法 宣告方法 解釋
Method getMethod(String name, Class<?>... parameterTypes)獲取指定方法名稱引數型別公共成員方法
Method[] getMethods()獲取所有的公共成員方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes)獲取指定方法名稱引數型別成員方法,不再限制訪問修飾符。
Method[] getDeclaredMethods()獲取所有的公共成員方法,不再限制訪問修飾符。

當獲取方法後,可以通過invoke()執行該方法。

Object invoke(Object obj, Object... args)  

可以通過getName()獲取方法名稱。