1. 程式人生 > 實用技巧 >文末送書四本 | 這篇Java反射機制太經典!不看後悔!

文末送書四本 | 這篇Java反射機制太經典!不看後悔!

先看再點贊,給自己一點思考的時間,如果對自己有幫助,微信搜尋【程式職場】關注這個執著的職場程式設計師。
價值:Java技能,面試經驗指導,簡歷優化,職場規劃指導,技能提升方法,講不完的職場故事,個人成長經驗。

01

概念

反射是Java的特徵之一,是一種間接操作目標物件的機制,核心是JVM在執行的時候才動態載入類,並且對於任意一個類,都能夠知道這個類的所有屬性和方法,呼叫方法/訪問屬性,不需要提前在編譯期知道執行的物件是誰,他允許執行中的Java程式獲取類的資訊,並且可以操作類或物件內部屬性。

程式中物件的型別一般都是在編譯期就確定下來的,而當我們的程式在執行時,可能需要動態的載入一些類,這些類因為之前用不到,所以沒有載入到jvm,這時,使用Java反射機制可以在執行期動態的建立物件並呼叫其屬性,它是在執行時根據需要才載入。

02

用途

只是知道概念還不能更明白反射到底是什麼?,那麼反射都在哪些用途上使用呢?我們開發中哪些情況下使用?

一般來說反射是用來做框架的,做一些抽象度比較高的底層程式碼。

反射是框架設計的靈魂。

反射都有哪些用途呢?

1、首先就是反編譯,反編譯是 .class-->.java

2、通過反射機制訪問java物件的屬性,方法,構造方法等

3、當我們在使用IDE,比如Ecplise時,當我們輸入一個物件或者類,並想呼叫他的屬性和方法是,一按點號,編譯器就會自動列出他的屬性或者方法,這裡就是用到反射。

4、反射最重要的用途就是開發各種通用框架。

03

解剖類

我們知道一個類裡一般有建構函式、方法、成員變數(欄位/屬性)。

Class物件提供瞭如下常用方法:

public Constructor getConstructor(Class<?>…parameterTypes)

public Method getMethod(String name,Class<?>… parameterTypes)

public Field getField(String name)

public Constructor getDeclaredConstructor(Class<?>…parameterTypes)

public Method getDeclaredMethod(String name,Class<?>… parameterTypes)

public Field getDeclaredField(String name)

這些方法分別用於幫咱們從類中解剖出建構函式、方法和成員變數(屬性)。

然後把解剖出來的部分,分別用Constructor、Method、Field物件表示。

首先要明白一點,我們寫的程式碼是儲存在後綴名是 .java的檔案裡的,但是它會被編譯,最終真正去執行的是編譯後的 .class檔案。

Java是面向物件的語言,一切皆物件,所以java認為 這些編譯後的 class檔案,這種事物也是一種物件,它也給抽象成了一種類,這個類就是Class,大家可以去AIP裡看一下這個類。

大家可以檢視api

04

常用類

Java.lang.Class;

Java.lang.reflect.Constructor;

Java.lang.reflect.Field;

Java.lang.reflect.Method;

Java.lang.reflect.Modifier;

05

例項

1,反射類中的方法

新增一個Person類,新增幾種引數的方法。

packagecom.cj.test;importjava.util.Date;public class Person {    public Person(){    System.out.println("預設的無參構造方法執行了");  }   public Person(String name){    System.out.println("姓名:"+name);  }    public Person(String name,int age){    System.out.println(name+"="+age);  }    private Person(int age){    System.out.println("年齡:"+age);  }    public void m1() {    System.out.println("m1");  }    public void m2(String name) {    System.out.println(name);  }    public String m3(String name,int age) {    System.out.println(name+":"+age);    return "aaa";  }    private void m4(Date d) {    System.out.println(d);  }    public static void m5() {    System.out.println("m5");  }    public static void m6(String[] strs) {    System.out.println(strs.length);  }   public static void main(String[] args) {    System.out.println("main");}}

下面我們來看一下呼叫。

packagecom.cj.test;import java.lang.reflect.Method;import java.util.Date;import org.junit.Test; publicclassTest1{   @Test//public void m1()  public void test1() throws Exception{    Class clazz = Class.forName("com.cj.test.Person");    Person p = (Person)clazz.newInstance();    Method m = clazz.getMethod("m1", null);    m.invoke(p, null);  }  @Test//public void m2(String name)  public void test2() throws Exception{    Class clazz = Person.class;    Person p = (Person) clazz.newInstance();    Method m = clazz.getMethod("m2", String.class);m.invoke(p,"程式職場");  }  @Test//public String m3(String name,int age)  public void test3() throws Exception{    Class clazz = Person.class;    Person p = (Person) clazz.newInstance();    Method m = clazz.getMethod("m3", String.class,int.class);    String returnValue = (String)m.invoke(p, "程式職場",23);    System.out.println(returnValue);  }  @Test//private void m4(Date d)  public void test4() throws Exception{    Class clazz = Person.class;    Person p = (Person) clazz.newInstance();    Method m = clazz.getDeclaredMethod("m4", Date.class);    m.setAccessible(true);    m.invoke(p,new Date());  }  @Test//public static void m5()  public void test5() throws Exception{    Class clazz = Person.class;    Method m = clazz.getMethod("m5", null);    m.invoke(null,null);  }  @Test//private static void m6(String[] strs)  public void test6() throws Exception{    Class clazz = Person.class;    Method m = clazz.getDeclaredMethod("m6",String[].class);    m.setAccessible(true);    m.invoke(null,(Object)new String[]{"a","b"});  }  @Test  public void test7() throws Exception{    Class clazz = Person.class;    Method m = clazz.getMethod("main",String[].class);    m.invoke(null,new Object[]{new String[]{"a","b"}});  }}


2,反射類中的屬性欄位

packagecom.cj.test;importjava.util.Date;publicclassPerson{publicStringname="程式職場";  private int age = 18;  public static Date time;    public int getAge() {    return age;  }    public Person(){    System.out.println("預設的無參構造方法執行了");  }   public Person(String name){    System.out.println("姓名:"+name);  }    public Person(String name,int age){    System.out.println(name+"="+age);  }    private Person(int age){    System.out.println("年齡:"+age);  }    public void m1() {    System.out.println("m1");  }    public void m2(String name) {    System.out.println(name);  }    public String m3(String name,int age) {    System.out.println(name+":"+age);    return "aaa";  }    private void m4(Date d) {    System.out.println(d);  }    public static void m5() {    System.out.println("m5");  }    public static void m6(String[] strs) {    System.out.println(strs.length);  }    public static void main(String[] args) {    System.out.println("main");}}

結果呼叫。

packagecom.cj.test;import java.lang.reflect.Field;import java.util.Date;import org.junit.Test; public class Demo3 {  //public String name="李四";  @Test  public void test1() throws Exception{    Class clazz = Person.class;    Person p = (Person)clazz.newInstance();    Field f = clazz.getField("name");    String s = (String)f.get(p);    System.out.println(s);        //更改name的值    f.set(p, "王六");    System.out.println(p.name);  }  @Test//private int age = 18;  public void test2() throws Exception{    Class clazz = Person.class;    Person p = (Person)clazz.newInstance();    Field f = clazz.getDeclaredField("age");    f.setAccessible(true);    int age = (Integer)f.get(p);    System.out.println(age);        f.set(p, 28);    age = (Integer)f.get(p);    System.out.println(age);  }  @Test//public static Date time;  public void test3() throws Exception{    Class clazz = Person.class;    Field f = clazz.getField("time");    f.set(null, new Date());    System.out.println(Person.time);  }}

3,反射方法的其他使用--通過反射越過泛型檢查

import java.lang.reflect.Method;importjava.util.ArrayList;/* * 通過反射越過泛型檢查 * 例如:有一個String泛型的集合,怎樣能向這個集合中新增一個Integer型別的值? */public class Demo {  public static void main(String[] args) throws Exception{    ArrayList<String> strList = new ArrayList<>();    strList.add("aaa");    strList.add("bbb");      //  strList.add(100);    //獲取ArrayList的Class物件,反向的呼叫add()方法,新增資料    Class listClass = strList.getClass(); //得到 strList 物件的位元組碼 物件    //獲取add()方法    Method m = listClass.getMethod("add", Object.class);    //呼叫add()方法    m.invoke(strList, 100);        //遍歷集合    for(Object obj : strList){      System.out.println(obj);    }  }}

講了這麼多,趕緊試試吧,在專案使用中更方便。

本文 Github ( 碼雲Gitee同步) https://github.com/ProceduralZC/JavaDevGuide/tree/master/code/JavaBasic 已收錄,歡迎 star。

文末送書

文末送書時刻!送的書分別是:

Node.js企業級應用開發實戰(北京大學出版社提供 3本)

Redis設計與實現 (機械工業出版社提供 1本)

在此感謝北京大學出版社機械工業出版社的支援。

送書規矩

從留言區中選中獎者,按照留言者的點贊,分享數選擇,點贊,分享數高者獲得書一本,累計送書 四本。時間截止9月18日的20點。

送的書籍

Node.js企業級應用開發實戰

Redis設計與實現

我是【爾東雙月】一枚執著的職場程式設計師,微信搜尋【程式職場】關注我。別忘了三連啊,點贊、收藏、留言,隨意給,我不挑。
注:如果文章有任何問題,歡迎毫不留情地指正。