版权声明:版权声明:本文为博主原创文章,转载请注明出处。 https://blog.youkuaiyun.com/lililuni/article/details/83449088 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
<div id="content_views" class="markdown_views prism-tomorrow-night">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p> 学到spring框架的时候,发现反射思想很重要,故特此写下此文,以加深理解。</p>
文章目录
1:反射概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
实际上,我们创建的每一个类也都是对象,即类本身是java.lang.Class类的实例对象。这个实例对象称之为类对象,也就是Class对象。那么,Class对象又是什么对象呢?
2:Class对象特点
下图是Class类的api(图片来自于Java基础之—反射(非常重要))
从图中可以得出以下几点:
- Class 类的实例对象表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有很多的实例,每个类都有唯一的Class对象。
- Class 类没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机自动构造的。也就是说我们不需要创建,JVM已经帮我们创建了。
- Class 对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法
3:反射的使用
假设我们现在有一个Hero类
package pojo;
public class Hero {
public String name; //姓名
public float hp; //血量
public float armor; //护甲
public int moveSpeed; //移动速度
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
1:获取类对象
获取类对象有3种方式
Class.forName()
(常用)Hero.class
new Hero().getClass()
在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样。(此处准确是在ClassLoader下,只有一个类对象)
示例:
package pojo; public class ObjectTest {
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span> String className <span class="token operator">=</span> <span class="token string">"pogo.Hero"</span><span class="token punctuation">;</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token comment">//获取类对象的第一种方式</span> Class <span class="token class-name">pClass1</span> <span class="token operator">=</span> Class<span class="token punctuation">.</span><span class="token function">forName</span><span class="token punctuation">(</span>className<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取类对象的第二种方式</span> Class <span class="token class-name">pClass2</span> <span class="token operator">=</span> Hero<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">;</span> <span class="token comment">//获取类对象的第三种方式</span> Class <span class="token class-name">pClass3</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Hero</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>pClass1<span class="token operator">==</span>pClass2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//输出true</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>pClass1<span class="token operator">==</span>pClass3<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//输出true</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ClassNotFoundException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// TODO Auto-generated catch block</span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
三种方式中,常用第一种,第二种需要导入类的包,依赖太强,不导包就抛编译错误。第三种对象都有了还要反射干什么。一般都第一种,一个字符串可以传入也可写在配置文件中等多种方法。
2 利用反射机制创建对象
基本步骤
与传统的通过new 来获取对象的方式不同反射机制,反射会先拿到Hero的“类对象”,然后通过类对象获取“构造器对象”再通过构造器对象创建一个对象,具体步骤:
1.获取类对象
Class class = Class.forName("pojo.Hero");
2.获取构造器对象Constructor con = clazz.getConstructor(形参.class);
3 获取对象Hero hero =con.newInstance(实参);
上面是最简单的获取方法,当Hero的构造方法不是无参构造方法时,获取构造器对象略有不同,见下面测试:
构造方法不同时,获取构造器对象的方法
示例:
- Hero类添加6种构造方法
//---------------构造方法------------------- //(默认的构造方法) Hero(String str){ System.out.println("(默认)的构造方法 s = " + str); }
<span class="token comment">//无参构造方法</span> <span class="token keyword">public</span> <span class="token function">Hero</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"调用了公有、无参构造方法执行了。。。"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//有一个参数的构造方法</span> <span class="token keyword">public</span> <span class="token function">Hero</span><span class="token punctuation">(</span><span class="token keyword">char</span> name<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"姓名:"</span> <span class="token operator">+</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//有多个参数的构造方法</span> <span class="token keyword">public</span> <span class="token function">Hero</span><span class="token punctuation">(</span>String name <span class="token punctuation">,</span><span class="token keyword">float</span> hp<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"姓名:"</span><span class="token operator">+</span>name<span class="token operator">+</span><span class="token string">"血量:"</span><span class="token operator">+</span> hp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//受保护的构造方法</span> <span class="token keyword">protected</span> <span class="token function">Hero</span><span class="token punctuation">(</span><span class="token keyword">boolean</span> n<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"受保护的构造方法 n = "</span> <span class="token operator">+</span> n<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//私有构造方法</span> <span class="token keyword">private</span> <span class="token function">Hero</span><span class="token punctuation">(</span><span class="token keyword">float</span> hp<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"私有的构造方法 血量:"</span><span class="token operator">+</span> hp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
- 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
- 通过反射机制获取对象
package test; public class ConstructorTest {
<span class="token comment">/* * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员; * * 1.获取构造方法: * 1).批量的方法: * public Constructor[] getConstructors():所有"公有的"构造方法 public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) * 2).获取单个的方法,并调用: * public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法: * public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有; * * 2.创建对象 * Constructor对象调用newInstance(Object... initargs) */</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> Exception <span class="token punctuation">{</span> <span class="token comment">//1.加载Class对象</span> Class <span class="token class-name">clazz</span> <span class="token operator">=</span> Class<span class="token punctuation">.</span><span class="token function">forName</span><span class="token punctuation">(</span><span class="token string">"pojo.Hero"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//2.获取所有公有构造方法</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"**********************所有公有构造方法*********************************"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Constructor<span class="token punctuation">[</span><span class="token punctuation">]</span> conArray <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getConstructors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span><span class="token punctuation">(</span>Constructor c <span class="token operator">:</span> conArray<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"************所有的构造方法(包括:私有、受保护、默认、公有)***************"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> conArray <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getDeclaredConstructors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span><span class="token punctuation">(</span>Constructor c <span class="token operator">:</span> conArray<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"*****************获取公有、无参的构造方法*******************************"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Constructor con <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getConstructor</span><span class="token punctuation">(</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型</span> <span class="token comment">//2>、返回的是描述这个无参构造函数的类对象。</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"con = "</span> <span class="token operator">+</span> con<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用构造方法</span> Object obj <span class="token operator">=</span> con<span class="token punctuation">.</span><span class="token function">newInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"******************获取私有构造方法,并调用*******************************"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> con <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getDeclaredConstructor</span><span class="token punctuation">(</span><span class="token keyword">float</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>con<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用构造方法</span> con<span class="token punctuation">.</span><span class="token function">setAccessible</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//暴力访问(忽略掉访问修饰符)</span> obj <span class="token operator">=</span> con<span class="token punctuation">.</span><span class="token function">newInstance</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 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
- 53
- 54
- 55
- 56
- 57
- 58
- 59
输出:
**********************所有公有构造方法*********************************
public pojo.Hero(java.lang.String,float)
public pojo.Hero(char)
public pojo.Hero()
************所有的构造方法(包括:私有、受保护、默认、公有)***************
private pojo.Hero(float)
protected pojo.Hero(boolean)
public pojo.Hero(java.lang.String,float)
public pojo.Hero(char)
public pojo.Hero()
pojo.Hero(java.lang.String)
*****************获取公有、无参的构造方法*******************************
con = public pojo.Hero()
调用了公有、无参构造方法执行了。。。
******************获取私有构造方法,并调用*******************************
private pojo.Hero(float)
私有的构造方法 血量:100.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
总结:
1.获取构造器对象方法:
1).批量的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2).获取单个的方法:
public Constructor getConstructor(Class… parameterTypes): 获取单个的"公有的"构造方法
public Constructor getDeclaredConstructor(Class…parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
3: 获取成员变量并使用
基本步骤
1.获取HeroPlus类的对象
new方法/第2章中的方法
h
2. 获取属性Field f1 = h.getDeclaredField("属性名")
3. 修改属性f1.set(h,实参)
,注意这里的h是对象,不是类对象
示例:
- 新增HeroPlus类
package pojo; public class HeroPlus { public String name; public float hp; public int damage; public int id;
<span class="token keyword">public</span> String <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span>String name<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token function">HeroPlus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token function">HeroPlus</span><span class="token punctuation">(</span>String string<span class="token punctuation">)</span> <span class="token punctuation">{</span> name <span class="token operator">=</span>string<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> String <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">"Hero [name="</span> <span class="token operator">+</span> name <span class="token operator">+</span> <span class="token string">"]"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">isDead</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// TODO Auto-generated method stub</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">attackHero</span><span class="token punctuation">(</span>HeroPlus h2<span class="token punctuation">)</span> <span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">+</span> <span class="token string">" 正在攻击 "</span> <span class="token operator">+</span> h2<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 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
- 获取属性并修改
package test; public class ParaTest { public static void main(String[] args) { HeroPlus h =new HeroPlus(); //使用传统方式修改name的值为garen h.name = "garen";
<span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token comment">//获取类HeroPlus的名字叫做name的字段</span> Field f1<span class="token operator">=</span> h<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getDeclaredField</span><span class="token punctuation">(</span><span class="token string">"name"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//修改这个字段的值</span> f1<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>h<span class="token punctuation">,</span> <span class="token string">"teemo"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//打印被修改后的值</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>h<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// TODO Auto-generated catch block</span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
补充:
getField和getDeclaredField的区别
getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是 不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
4: 获取成员方法并使用
- 获取HeroPlus类的对象
h
- 获取成员方法:
public Method getMethod(String name ,Class<?>… parameterTypes):获取"公有方法";(包含了父类的方法也包含Object类)
public Method getDeclaredMethods(String name ,Class<?>… parameterTypes) :获取成员方法,包括私有的(不包括继承的)
参数解释:
name : 方法名;
Class … : 形参的Class类型对象- 调用方法
Method --> public Object invoke(Object obj,Object… args):
参数说明:
obj : 要调用方法的对象;
args:调用方式时所传递的实参;
示例:
package test; public class MethodTest { public static void main(String[] args) {
HeroPlus h <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HeroPlus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token comment">// 获取这个名字叫做setName,参数类型是String的方法</span> Method m <span class="token operator">=</span> h<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token string">"setName"</span><span class="token punctuation">,</span> String<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 对h对象,调用这个方法</span> m<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>h<span class="token punctuation">,</span> <span class="token string">"盖伦"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 使用传统的方式,调用getName方法</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>h<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// TODO Auto-generated catch block</span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
5: 获取main方法并使用
示例:
- HeroPlus 新增main方法
public static void main(String[] args) {
System.out.println("执行main方法");
}
- 1
- 2
- 3
- 通过下面步骤获取main方法1
package test; public class MainTest { public static void main(String[] args) { try { //1、获取HeroPlus对象的字节码 Class clazz = Class.forName("pojo.HeroPlus");
<span class="token comment">//2、获取main方法,第一个参数:方法名称,第二个参数:方法形参的类型,</span> Method methodMain <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token string">"main"</span><span class="token punctuation">,</span> String<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//3、调用main方法</span> <span class="token comment">// methodMain.invoke(null, new String[]{"a","b","c"});</span> <span class="token comment">//第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组,这里要注意在jdk1.4时是数组,jdk1.5之后是可变参数</span> <span class="token comment">//这里拆的时候将 new String[]{"a","b","c"} 拆成3个对象。所以需要将它强转。</span> methodMain<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>null<span class="token punctuation">,</span> <span class="token punctuation">(</span>Object<span class="token punctuation">)</span><span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string">"b"</span><span class="token punctuation">,</span><span class="token string">"c"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//方式一</span> <span class="token comment">// methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
4 : 反射的其他用处
反射非常强大,但是学习了之后,会不知道该如何使用,反而觉得还不如直接调用方法来的直接和方便2。
通常来说,需要在学习了Spring 的依赖注入,反转控制之后,才会对反射有更好的理解,但是刚学到这里的同学,不一定接触了Spring,所以在这里举两个例子,来演示一下反射的一种实际运用。
1:通过反射运行配置文件内容
- 首先准备两个业务类
package service;
public class Service1 {
public void doService1(){
System.out.println("业务方法1");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
package service;
public class Service2 {
public void doService2(){
System.out.println("业务方法2");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 当需要从第一个业务方法切换到第二个业务方法的时候,使用非反射方式,必须修改代码,并且重新编译运行,才可以达到效果
package service;
public class CommonTest {
public static void main(String[] args) {
//new Service1().doService1();
//必须重新修改代码
new Service2().doService2();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 使用反射方式则方便很多
- 首先准备一个配置文件,就叫做spring.txt吧, 放在src目录下。
里面存放的是类的名称,和要调用的方法名。首先准备一个配置文件,就叫做spring.txt吧, 放在src目录下。里面存放的是类的名称,和要调用的方法名。- 在测试类Test中,首先取出类名称和方法名,然后通过反射去调用这个方法。
- 当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。
示例:
spring.txt内容
class=reflection.Service1
method=doService1
- 1
- 2
测试类
package service; public class ReflectTest { @SuppressWarnings({ "rawtypes", "unchecked" }) public static void main(String[] args) throws Exception {
<span class="token comment">//从spring.txt中获取类名称和方法名称</span> File springConfigFile <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">File</span><span class="token punctuation">(</span><span class="token string">"H:\\eclpise-workspace\\reflect-demo\\src\\spring.txt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> Properties springConfig<span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Properties</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> springConfig<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">FileInputStream</span><span class="token punctuation">(</span>springConfigFile<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> String className <span class="token operator">=</span> <span class="token punctuation">(</span>String<span class="token punctuation">)</span> springConfig<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> String methodName <span class="token operator">=</span> <span class="token punctuation">(</span>String<span class="token punctuation">)</span> springConfig<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"method"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//根据类名称获取类对象</span> Class <span class="token class-name">clazz</span> <span class="token operator">=</span> Class<span class="token punctuation">.</span><span class="token function">forName</span><span class="token punctuation">(</span>className<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//根据方法名称,获取方法对象</span> Method m <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span>methodName<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取构造器</span> Constructor c <span class="token operator">=</span> clazz<span class="token punctuation">.</span><span class="token function">getConstructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//根据构造器,实例化出对象</span> Object service <span class="token operator">=</span> c<span class="token punctuation">.</span><span class="token function">newInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用对象的指定方法</span> m<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>service<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 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
2:通过反射越过泛型检查
泛型是在编译期间起作用的。在编译后的.class文件中是没有泛型的。所有比如T或者E类型啊,本质都是通过Object处理的。所以可以通过使用反射来越过泛型。
示例:
package test; public class GenericityTest { public static void main(String[] args) throws Exception{
ArrayList<span class="token generics function"><span class="token punctuation"><</span>String<span class="token punctuation">></span></span> list <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token operator"><</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"this"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"is"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// strList.add(5);报错</span> <span class="token comment">/********** 越过泛型检查 **************/</span> <span class="token comment">//获取ArrayList的Class对象,反向的调用add()方法,添加数据</span> Class <span class="token class-name">listClass</span> <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取add()方法</span> Method m <span class="token operator">=</span> listClass<span class="token punctuation">.</span><span class="token function">getMethod</span><span class="token punctuation">(</span><span class="token string">"add"</span><span class="token punctuation">,</span> Object<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用add()方法</span> m<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>list<span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//遍历集合</span> <span class="token keyword">for</span><span class="token punctuation">(</span>Object obj <span class="token operator">:</span> list<span class="token punctuation">)</span><span class="token punctuation">{</span> System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
}
- 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
反射部分先记录到这。
接下来计划认真理解下spring的依赖注入和反转控制!
GitHub源码:java反射
</div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet">
</div>