1. 程式人生 > >Java型別資訊與用反射機制編寫通用的Excel匯入匯出

Java型別資訊與用反射機制編寫通用的Excel匯入匯出

Java類檔案編譯後,會在類中新增一個靜態屬性,這個屬性就是Class類的例項,用於描述型別資訊。描述類資訊的架構圖如: 
這裡寫圖片描述 
Class物件提供了一組方法,讓我們可以方便獲取類的屬性,方法,構造方法等資訊,並且用Field,Method,Constructor類來描述,可以用這些類來分析型別資訊和執行型別資訊來進行一些動態操作,例如反射,動態代理,依賴注入/控制反轉等

Class類

Classl類的物件用來表示執行時的類或介面資訊,可以通過Class物件獲取類名,父類資訊,還可以通過Class類獲取該類的屬性,方法,構造方法等 
1. 通過.class屬性 
2. 通過getClass()方法 
3. 通過forName()方法

package xls;
public class ClassTest {
    public void print(String str){
        System.out.println("Hello "+str);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
package xls;
public class ClassTestMain {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //通過.class
屬性 Class<ClassTest> clazz1 = ClassTest.class; System.out.println("通過.class屬性: "+clazz1.getCanonicalName()); //通過getClass()方法 ClassTest classTest = new ClassTest(); Class<? extends ClassTest> clazz2 = classTest.getClass(); System.out.println
("通過getClass()方法: "+clazz2.getCanonicalName()); //通過forName(className)方法 className為完整名字 Class<?> clazz3 = Class.forName("xls.ClassTest"); System.out.println("通過forName()方法: "+clazz3.getCanonicalName()); //用三種方法獲取的Class物件例項化ClassTest ClassTest classTest1 = clazz1.newInstance(); classTest1.print("classTest1"); ClassTest classTest2 = clazz2.newInstance(); classTest2.print("classTest2"); ClassTest classTest3 = (ClassTest) clazz3.newInstance(); classTest3.print("classTest3"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

執行結果: 
這裡寫圖片描述

獲取Constructor物件

有四種方式獲取構造方法的Constructor物件 
1. getConstructor(Class,parameterTypes…)用於獲取指定引數型別的Constructor物件 
但是不能獲取私有的構造方法的物件 
2. getDeclaredConstructor(Class,paramerterTypes..) 用於獲取指定引數型別的Constructor物件 
但是能獲取公有和私有的構造方法的Constructor物件 
3. getConstructors()用於獲取所有公有構造方法描述物件,若沒有共有建構函式時返回長度為0的陣列 
4. getDeclaredConstructors()用於獲取所有公有和被保護的構造方法描述物件

package xls;
import java.lang.reflect.Constructor;
public class ConstructorTest {
    /**
     * 建構函式發生過載時,下方的無參構造方法被註釋掉的話,則變成沒有無參構造方法,
     * 當使用Constructor constructor1 = clazz1.getConstructor();就會報錯
     * 因為這種情況並沒有無參構造方法
     * 但是當沒有寫構造方法時,則會有一個預設的無參構造方法使用
     * Constructor constructor1 = clazz1.getConstructor();則沒有問題
     */
    public ConstructorTest(){} 
    public ConstructorTest(String name){}
    public ConstructorTest(String name,int age){}
    protected ConstructorTest(int age){}
    private ConstructorTest(double salary){}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
package xls;
import java.lang.reflect.Constructor;
public class ConstructorTestMain {
    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        /**
         * 1.getConstructor(Class...parameterTypes)用於獲取指定引數型別的Constructor物件
         * 但是不能獲取私有的構造方法的物件
         * 
         * 2.getDeclaredConstructor(Class...paramerterTypes) 用於獲取指定引數型別的Constructor物件
         *  但是能獲取公有和私有的構造方法的Constructor物件
         */
        Class clazz1 = ConstructorTest.class;//有三種方式獲取Class物件

        //獲取無參構造方法,要注意有沒有無參構造方法
        Constructor constructor1 = clazz1.getConstructor();
        System.out.println(constructor1.toString());
        //獲取指定引數型別的Constructor物件
        Constructor constructor2= clazz1.getConstructor(String.class);
        System.out.println(constructor2.toString());
        Constructor constructor3= clazz1.getConstructor(String.class,int.class);
        System.out.println(constructor3.toString());
        //下方的程式碼會報錯,因為getConstructor()不能獲取私有屬性的
        //Constructor constructor4= clazz1.getConstructor(int.class);
        //System.out.println(constructor4.toString());
        //Constructor constructor5= clazz1.getConstructor(double.class);
        //System.out.println(constructor5.toString());
        System.out.println("<===============2===============>");
        //獲取指定型別的被保護的構造方法的物件
        Constructor constructor6 = clazz1.getDeclaredConstructor(int.class);
        System.out.println(constructor6.toString());
        Constructor constructor7 = clazz1.getDeclaredConstructor(double.class);
        System.out.println(constructor7.toString());

        System.out.println("<===============3===============>");

        /**
         * 3.getConstructors()用於獲取所有公有構造方法描述物件,若沒有共有建構函式時返回長度為0的陣列
         * 4.getDeclaredConstructors()用於獲取所有公有和被保護的構造方法描述物件
         */
        Constructor[] constructor8 = clazz1.getConstructors();
        for(Constructor c :constructor8){
            System.out.println(c.toString());
        }
        System.out.println("<===============4===============>");
        Constructor[] constructor9 = clazz1.getDeclaredConstructors();
        for(Constructor c :constructor9){
            System.out.println(c.toString());
        }


    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

執行結果: 
這裡寫圖片描述

獲取Method物件

Method的物件用於描述類的單個方法(不包構造方法),可以通過它來獲取方法的訪問許可權,引數型別,返回值的型別等資訊,還可以根據Method的物件來動態執行。

package xls;
public class MethodTest {
    public void hello(){}
    private void student(String name){}
    public void teacher(String name){
        System.out.println("Hello "+name);
    } 
    public final void school(){}
}
package xls;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MethodMain {
    public static void main(String[] args) throws ClassNotFoundException, 
    NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException,
    IllegalArgumentException, InvocationTargetException {
        /**
         * 獲取Method的四種方法與獲取Constructor的四種方法相似,用法相似
         * 1.getMthod(String name,Class...parameterTypes)用於獲取指定名稱和引數型別的公有方法的描述物件,
         * ,不能用來獲取私有和被保護的物件
         * 2.getDeclaredMethod(String name,Class...parameterTypes)作用和第一個相同,
         * 但可以獲取來獲取非公有的方法描述物件
         */
        Class<?> clazz = Class.forName("xls.MethodTest");
        Method method1 = clazz.getMethod("hello", null);
        Method method3 = clazz.getMethod("teacher", String.class);
//      Method method2 = clazz.getMethod("student", String.class);
        Method method4 = clazz.getMethod("school",