文末送書四本 | 這篇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設計與實現
我是【爾東雙月】一枚執著的職場程式設計師,微信搜尋【程式職場】關注我。別忘了三連啊,點贊、收藏、留言,隨意給,我不挑。
注:如果文章有任何問題,歡迎毫不留情地指正。