一、Java反射的理解(反射是研究框架的基础之一)
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
二、逐步分析
参考:https://blog.****.net/u012585964/article/details/52011138
1、关于Class
1、Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性
2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。 一个 Class 对象包含了特定某个类的有关信息。
4、Class 对象只能由系统建立对象
5、一个类在 JVM 中只会有一个Class实例
下面创建一个例子:后面的分析均以此案例为基准。
创建一个空接口:(后面会不断补充)
package com.xfwl.reflection; public interface IHuman { }
创建一个空基类:(后面会不断补充)
package com.xfwl.reflection; public class Human { }
创建一个子类:(后面会不断补充)
package com.xfwl.reflection; public class Person extends Human implements IHuman {
/**
* 默认default修饰
*/
String name;
/**
* private修饰
*/
private int age;
/**
* public修饰
*/
public char sex='M';
/**
* 无参构造
*/
public Person(){
System.out.println("无参构造!!!");
}
/**
* 有参构造
*/
public Person(String name,int age,char sex){
System.out.println("有参构造!!!");
this.name=name;
this.age=age;
this.sex=sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
2、反射获取类对象的三种方式(通过一个Junit测试来说明)
package com.xfwl.reflection; import org.junit.Test;
/**
* 测试类
* @function
* @author 小风微凉
* @time 2018-6-3 下午12:28:38
*/
public class TestAction {
/**
* 反射机制获取类有三种方法
*/
@Test
public void testGetClass() throws ClassNotFoundException {
Class clazz = null; //1 直接通过类名.Class的方式得到
clazz = Person.class;
System.out.println("通过类名: " + clazz); //2 通过对象的getClass()方法获取,这个使用的少(一般是传的是Object,不知道是什么类型的时候才用)
Object obj = new Person();
clazz = obj.getClass();
System.out.println("通过getClass(): " + clazz); //3 通过全类名获取,用的比较多,但可能抛出ClassNotFoundException异常
clazz = Class.forName("com.xfwl.reflection.Person");
System.out.println("通过全类名获取: " + clazz);
}
}
运行结果:
通过类名: class com.xfwl.reflection.Person
无参构造!!!
通过getClass(): class com.xfwl.reflection.Person
通过全类名获取: class com.xfwl.reflection.Person
特别注意:(以下2中方式不会调用构造方法,因为没有实例化操作)
//1 直接通过类名.Class的方式得到
clazz = Person.class;
//3 通过全类名获取,用的比较多,但可能抛出ClassNotFoundException异常
clazz = Class.forName("com.xfwl.reflection.Person");
3、利用newInstance创建对象:调用的类必须有无参的构造器
/**
* Class类的newInstance()方法,创建类的一个对象。
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
@Test
public void testNewInstance()
throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class clazz = Class.forName("com.xfwl.reflection.Person"); //使用Class类的newInstance()方法创建类的一个对象
//实际调用的类的那个 无参数的构造器(这就是为什么写的类的时候,要写一个无参数的构造器,就是给反射用的)
//一般的,一个类若声明了带参数的构造器,也要声明一个无参数的构造器
Object obj = clazz.newInstance();
System.out.println(obj);
}
测试结果:
那么,如果删除Person.java中的无参构造,继续测试,结果如下:
4、ClassLoader类加载器
类加载器详解:
http://blog.****.net/ochangwen/article/details/51473120
/**
* ClassLoader类装载器
*/
@Test
public void testClassLoader1() throws ClassNotFoundException, IOException {
//1、获取一个系统的类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println("系统的类加载器-->" + classLoader); //2、获取系统类加载器的父类加载器(扩展类加载器(extensions classLoader))
classLoader = classLoader.getParent();
System.out.println("扩展类加载器-->" + classLoader); //3、获取扩展类加载器的父类加载器
//输出为Null,无法被Java程序直接引用
classLoader = classLoader.getParent();
System.out.println("启动类加载器-->" + classLoader); //4、测试当前类由哪个类加载器进行加载 ,结果就是系统的类加载器
classLoader = Class.forName("com.xfwl.reflection.Person").getClassLoader();
System.out.println("当前类由哪个类加载器进行加载-->"+classLoader); //5、测试JDK提供的Object类由哪个类加载器负责加载的
//输出为Null,无法被Java程序直接引用
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println("JDK提供的Object类由哪个类加载器加载-->" + classLoader);
}
测试结果:
系统的类加载器-->sun.misc.Launcher$AppClassLoader@18b4aac2
扩展类加载器-->sun.misc.Launcher$ExtClassLoader@614c5515
启动类加载器-->null
当前类由哪个类加载器进行加载-->sun.misc.Launcher$AppClassLoader@18b4aac2
JDK提供的Object类由哪个类加载器加载-->null
5、反射机制通过加载器获取流对象:getResourceAsStream方法
/**
* 反射机制通过加载器获取流对象:getResourceAsStream方法
* @throws ClassNotFoundException
* @throws IOException
*/
@Test
public void testGetResourceAsStream() throws ClassNotFoundException, IOException {
//调用getResourceAsStream 获取类路径下的文件对应的输入流
/**
* 特别说明:
* getResourceAsStream("path"),path的路径和new Person()的位置有关
*/ InputStream in = new Person().getClass().getClassLoader()
.getResourceAsStream("com/xfwl/reflection/test.properties");
System.out.println("in: " +in); Properties properties = new Properties();
properties.load(in);
System.out.println("文件内容:"+properties);
System.out.println("name: "+properties.getProperty("name"));
System.out.println("age: " + properties.getProperty("age"));
System.out.println("sex: "+properties.getProperty("sex"));
System.out.println("desc: " + properties.getProperty("desc"));
}
test.properties文件内容如下:文件编码格式:ISO-8859-1
name=\u5C0F\u98CE\u5FAE\u51C9\u0087\u0089
age=23
sex=M
desc=\u53CD\u5C04\u673A\u5236\u5B66\u4E60
运行结果:(直接解析会出现乱码问题,这个可以通过new String(乱码格式处理参数)来处理)
无参构造!!!
in: java.io.BufferedInputStream@215be6bb
文件内容:{age=23, name=小风微凉??, sex=M, desc=反射机制学习}
name: 小风微凉??
age: 23
sex: M
desc: 反射机制学习
6、反射机制获取类中的方法:Method: 对应类中的方法
现在给Person类添加一个private 方法、一个public 方法、一个defaut 方法、一个protected方法
/**
* Java权限有四个,分别为public,protected,默认,private,其开放程度依次降低
* public可供所有类访问
* protected继承可见
* private只能类本身内部的方法可以访问
*/
public void method_public(){
System.out.println("method_public");
}
public void method_public_2(String name,int age,char sex){//public 带参数
System.out.println("method_public_2");
String info="Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
System.out.println(info);
}
protected void method_protected(){
System.out.println("method_protected");
}
protected void method_protected_2(String info){//protected 带参数
System.out.println("method_protected_2:"+info);
}
void method_default(){
System.out.println("method_default");
}
void method_default_2(String info){//默认修饰符 带参数
System.out.println("method_default_2:"+info);
}
private void method_private(){
System.out.println("method_private");
}
private void method_private_2(String info){//private 带参数
System.out.println("method_private_2:"+info);
}
开始测试如何通过反射机制使用这些方法
/**
* 如何通过反射机制使用这些方法
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
*/
@Test
public void testMethod() throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InstantiationException, InvocationTargetException {
Class clazz = Class.forName("com.xfwl.reflection.Person"); //1、得到clazz 对应的类中有哪些方法,不能获取private方法
Method[] methods =clazz.getMethods();
System.out.println("通过反射机制可以拿到的方法:clazz.getMethods()");
for (Method method : methods){
System.out.println(method.getName());
}
System.out.println("<-------------------------->"); //2、获取所有的方法(且只获取当着类声明的方法,包括private方法)
Method[] methods2 = clazz.getDeclaredMethods();
System.out.println("通过反射机制可以拿到的方法:clazz.getDeclaredMethods()");
for (Method method : methods2){
System.out.println(method.getName());
}
System.out.println("<-------------------------->");
System.out.println("通过反射机制可以拿到指定的方法:clazz.getDeclaredMethod()");
//3、获取指定的方法
Method method1= clazz.getDeclaredMethod("method_private");
System.out.println("private 无参:"+method1); Method method2 = clazz.getDeclaredMethod("method_private_2",String.class);//第一个参数是方法名,后面的是方法里的参数
System.out.println("private 有参:"+method2); Method method3 = clazz.getDeclaredMethod("method_public_2",String.class,int.class,char.class);//第一个参数是方法名,后面的是方法里的参数
System.out.println("public 有参:"+method2); //4、执行方法!
Object obj = clazz.newInstance();
method3.invoke(obj, "小风微凉", 23,'M'); //执行方法:invoke(类对象)
}
测试结果:
通过反射机制可以拿到的方法:clazz.getMethods():不能获取private/protected/default方法
toString
getName
setName
method_public_2
setAge
method_public
getSex
getAge
setSex
wait
wait
wait
equals
hashCode
getClass
notify
notifyAll
<-------------------------->
通过反射机制可以拿到的方法:clazz.getDeclaredMethods():获取所有修饰权限的方法
toString
getName
setName
method_private_2
method_private
method_public_2
setAge
method_public
method_default
method_default_2
getSex
getAge
setSex
method_protected
method_protected_2
<-------------------------->
通过反射机制可以拿到指定的方法:clazz.getDeclaredMethod()
private 无参:private void com.xfwl.reflection.Person.method_private()
private 有参:private void com.xfwl.reflection.Person.method_private_2(java.lang.String)
public 有参:private void com.xfwl.reflection.Person.method_private_2(java.lang.String)
无参构造!!!
method_public_2
Person{name='小风微凉', age=23, sex='M'}
继续分析一下:
JDK中的获取方法
获取方法:默认只能获取public修饰的方法
@CallerSensitive
public Method[] getMethods() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}
获取方法:所有修饰权限的方法都可以获得
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
获取方法:获取指定的方法(所有修饰权限)
/**
* @jls 8.2 Class Members
* @jls 8.4 Method Declarations
* @since JDK1.1
*/
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}
分析一下上面这个方法:
String name:方法的名称
Class<?>... parameterTypes:一个或多个方法参数的类型,注意要一一对应,否则会报错的哦
执行方法:invoke(方法对象,方法实际参数)
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
7、反射机制获取类中的方法:Method: 对应基类或接口中的方法
上面分析了,如何通过反射拿到当前本类里面的各个修饰权限的方法,下面来继续分析一下,如何读取父类或实现的接口中的方法:
现在,给父类添加一些方法,在接口中定义一些方法:
接口中的方法声明:
package com.xfwl.reflection; public interface IHuman { void eat();
void eat(String info);
}
Person.java实现接口方法
public void eat() {
System.out.println("实现接口的方法:eat()无参:");
}
public void eat(String info) {
System.out.println("实现接口的方法:eat()有参:"+info);
}
父类中的方法定义:
package com.xfwl.reflection; public class Human {
public void play_public(){
System.out.println("public无参:play_public");
}
public void play_public_2(String info){
System.out.println("public有参:play_public2:"+info);
}
protected void play_protected(){
System.out.println("protected无参:play_protected");
}
protected void play_protected_2(String info){
System.out.println("protected有参:play_protected_2:"+info);
}
void play_default(){
System.out.println("默认修饰符无参:play_default");
}
void play_default_2(String info){//默认修饰符 带参数
System.out.println("默认修饰符有参:play_default_2:"+info);
}
private void play_private(){
System.out.println("private无参:play_private");
}
private void play_private_2(String info){
System.out.println("private有参:play_private_2:"+info);
}
}
开始测试:
1、拿到当前Person类反射对象,能否得到接口中的方法
/**
* 反射机制获取类中的方法:Method: 对应基类或接口中的方法
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@Test
public void testInterfaceOrSupperClass() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
Class clazz = Class.forName("com.xfwl.reflection.Person");
//拿到当前Person类反射对象,能否得到接口中的方法
for (Method method : clazz.getMethods()){
System.out.println(method.getName());
}
//获取当前类实现的接口中的方法
Method method1= clazz.getDeclaredMethod("eat");
Method method2= clazz.getDeclaredMethod("eat",String.class);
//执行
method1.invoke(clazz.newInstance());
method2.invoke(clazz.newInstance(),"eat有参数");
}
测试结果:(可以拿到实现的接口中的方法并执行)
toString
getName
setName
eat
eat
method_public_2
setAge
getSex
setSex
getAge
method_public
play_public_2
play_public
wait
wait
wait
equals
hashCode
getClass
notify
notifyAll
无参构造!!!
实现接口的方法:eat()无参:
无参构造!!!
实现接口的方法:eat()有参:eat有参数
2、拿到当前Person类反射对象,能否获取父类中的方法
通过当前反射对象,拿到父类反射对象
Class clazz = Class.forName("com.xfwl.reflection.Person");
Class superClazz = clazz.getSuperclass();
/**
* 反射机制获取类中的方法:Method: 对应基类或接口中的方法
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@Test
public void testInterfaceOrSupperClass() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
Class clazz = Class.forName("com.xfwl.reflection.Person");
System.out.println("<------------父类中能够使用的公共权限的方法------------------------>");
//拿到当前Person类反射对象,能否获取父类中的方法
Class superClazz = clazz.getSuperclass();
for (Method method : superClazz.getMethods()){
System.out.println(method.getName());
}
System.out.println("<----------------父类中所有的方法:仅仅父类中的方法-------------------->");
//拿到父类中的所有权限修饰符修饰的方法
for (Method method : superClazz.getDeclaredMethods()){
System.out.println(method.getName());
}
}
运行结果:
<------------父类中能够使用的公共权限的方法------------------------>
play_public
play_public_2
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
<----------------父类中所有的方法:仅仅父类中的方法-------------------->
play_private_2
play_public
play_public_2
play_private
play_protected
play_default
play_protected_2
play_default_2
那么可以执行父类中的方法吗?
//是否可以通过子类对象拿到父类中的方法
Method method3= clazz.getDeclaredMethod("play_public");
Method method4= clazz.getDeclaredMethod("play_public_2",String.class);
Method method5= clazz.getDeclaredMethod("play_private");
Method method6= clazz.getDeclaredMethod("play_private_2",String.class);
上面代码报错,说明不可以,public修饰的方法也拿不到
Method method7= superClazz.getDeclaredMethod("play_public");
Method method8= superClazz.getDeclaredMethod("play_public_2",String.class);
Method method9= superClazz.getDeclaredMethod("play_private");
Method method10= superClazz.getDeclaredMethod("play_private_2",String.class);
上面代码正常执行,说明父类的反射对象可以拿到自己的public或private方法
//使用子类的反射对象执行方法
method7.invoke(clazz.newInstance());
method8.invoke(clazz.newInstance(), "play_public_2有参数");
method9.invoke(clazz.newInstance()); //无法执行,Junit报错
method10.invoke(clazz.newInstance(), "play_private_2有参数");//无法执行,Junit报错
//使用父类的反射对象执行方法
method7.invoke(superClazz.newInstance());
method8.invoke(superClazz.newInstance(), "play_public_2有参数");
method9.invoke(superClazz.newInstance()); //无法执行,Junit报错
method10.invoke(superClazz.newInstance(), "play_private_2有参数");//无法执行,Junit报错
上面代码执行部分报错,说明通过子类的反射对象和拿到的父类反射对象,也仅仅只能执行public和protected和default默认修饰的方法,不能执行private修饰的方法
7、反射机制获取类中的字段属性:Field字段
/**
* 默认default修饰
*/
String name;
/**
* private修饰
*/
private int age;
/**
* public修饰
*/
public char sex='M';
/**
* protected修饰
*/
protected boolean isBeauty=true;
开始测试:如何获取
/**
* 反射机制获取类中的字段属性:Field字段
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
@Test
public void testFiled() throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
//拿到反射Class对象
Class clazz = Class.forName("com.xfwl.reflection.Person");
//获取Field的数组,私有字段也能获取
Field[] fields = clazz.getDeclaredFields();
System.out.println("<----遍历拿到字段:开始--------------------->");
for (Field field: fields) {
System.out.println(field.getName());
}
System.out.println("<------------获取指定名字的Field以及类型--------------------------->");
//获取指定名字的Field(如果是私有的,见下面的4)
Field field1 = clazz.getDeclaredField("name");
System.out.println("获取指定Field名=: " + field1.getName()+",类型:"+field1.getType());
Field field2 = clazz.getDeclaredField("age");
System.out.println("获取指定Field名=: " + field2.getName()+",类型:"+field2.getType());
Field field3 = clazz.getDeclaredField("sex");
System.out.println("获取指定Field名=: " + field3.getName()+",类型:"+field3.getType());
Field field4 = clazz.getDeclaredField("isBeauty");
System.out.println("获取指定Field名=: " + field4.getName()+",类型:"+field4.getType()); System.out.println("<----------获取指定对象的Field的值 ----------------------------->");
Person person = new Person("小风微凉", 12,'M');
//获取指定对象的Field的值
Object val = field1.get(person);
System.out.println("获取指定对象字段'name'的Field的值=: " + val); System.out.println("<----------设置指定对象的Field的值----------------------------->");
//设置指定对象的Field的值
field1.set(person, "反射学习A");
System.out.println("设置指定对象字段'name'的Field的值=: " + person.name); System.out.println("<----------若该字段是私有的,需要调用setAccessible(true)方法----------------------------->");
//若该字段是私有的,需要调用setAccessible(true)方法
field2 = clazz.getDeclaredField("age");
field2.setAccessible(true);
System.out.println("获取指定私有字段名=: " + field2.getName());
}
测试结果:
<----遍历拿到字段:开始--------------------->
name
age
sex
isBeauty
<------------获取指定名字的Field以及类型--------------------------->
获取指定Field名=: name,类型:class java.lang.String
获取指定Field名=: age,类型:int
获取指定Field名=: sex,类型:char
获取指定Field名=: isBeauty,类型:boolean
<----------获取指定对象的Field的值 ----------------------------->
有参构造!!!
获取指定对象字段'name'的Field的值=: 小风微凉
<----------设置指定对象的Field的值----------------------------->
设置指定对象字段'name'的Field的值=: 反射学习A
<----------若该字段是私有的,需要调用setAccessible(true)方法----------------------------->
获取指定私有字段名=: age
8、反射机制获取类中的构造器:构造器(Constructor)
Person的构造器
/**
* 无参构造
*/
public Person(){
System.out.println("无参构造!!!");
}
/**
* 有参构造
*/
public Person(String name,int age,char sex){
System.out.println("有参构造!!!");
this.name=name;
this.age=age;
this.sex=sex;
}
@Test测试
/**
* 构造器:开发用的比较少
*/
@Test
public void testConstructor() throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException {
String className = "com.xfwl.reflection.Person";
Class<Person> clazz = (Class<Person>) Class.forName(className); //1.获取Constructor对象
Constructor<Person>[] constructors =
(Constructor<Person>[]) Class.forName(className).getConstructors(); System.out.println("<-------------打印所有的构造器---------------------->");
for (Constructor<Person> constructor: constructors) {
System.out.println(constructor);
}
System.out.println("<------------------------------------------------>");
Constructor<Person> constructor = clazz.getConstructor(String.class, int.class,char.class);
System.out.println("拿到指定的-->" + constructor); //2.调用构造器的newInstance()方法创建对象
Object obj= constructor.newInstance("changwen", 11,'M');
}
运行结果:
<-------------打印所有的构造器---------------------->
public com.xfwl.reflection.Person()
public com.xfwl.reflection.Person(java.lang.String,int,char)
<------------------------------------------------>
拿到指定的-->public com.xfwl.reflection.Person(java.lang.String,int,char)
有参构造!!!
9、反射机制获取类中的注解:注解(Annotation)
基本的 Annotation
自定义 Annotation
package com.xfwl.reflection; 3 import java.lang.annotation.ElementType;
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.annotation.Target; public class Person extends Human implements IHuman { @Retention(RetentionPolicy.RUNTIME) //运行时检验
@Target(value = {ElementType.METHOD}) //作用在方法上
public @interface AgeValidator { int min();
int max();
}
//......其余部分省略
}
/**
* 自定义一个注解:检查年龄范围
* @function
* @author 小风微凉
* @time 2018-6-3 下午3:56:03
*/
@Retention(RetentionPolicy.RUNTIME) //运行时检验
@Target(value = {ElementType.METHOD}) //作用在方法上
public @interface AgeValidator {
int min();
int max();
}
@Test测试
/**
* 通过反射才能获取注解
*/
@Test
public void testAnnotation() throws Exception {
//这样的方式不能使用注解
/*Person person3 = new Person();
person3.setAge(10);*/ //拿到反射Class对象
String className = "com.xfwl.reflection.Person";
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
//拿到指定方法
Method method = clazz.getDeclaredMethod("setAge",int.class);
int val =40; //获取注解
Annotation annotation = method.getAnnotation(AgeValidator.class);
if (annotation != null){
if (annotation instanceof AgeValidator){
AgeValidator ageValidator = (AgeValidator) annotation; if (val< ageValidator.min() || val>ageValidator.max()){
throw new RuntimeException("数值超出范围");
}
}
}
//执行方法
method.invoke(obj, val);
System.out.println(obj);
}
运行结果:
无参构造!!!
Person{name='null', age=40, sex='M'}
获取指定注解:
//获取注解
Annotation annotation = method.getAnnotation(AgeValidator.class);
获取所有注解:
//获取所有注解
Annotation[] arr=clazz.getDeclaredAnnotations();
提取 Annotation信息
JDK 的元Annotation
package com.xfwl.reflect; public class UserBean { private String uname;
private String upwd;
public UserBean(){
this.setUname("xfwl");
this.setUpwd("123456");
}
public UserBean(String uname,String upwd){
this.setUname(uname);
this.setUpwd(uname);
}
public void logIn(UserBean user){
System.out.println("用户登录:uname="+this.getUname()+",upwd="+this.getUpwd());
}
public String getUname() {
return uname;
}
private void logOut(UserBean user){
System.out.println("用户退出:uname="+this.getUname()+",upwd="+this.getUpwd());
}
public void setUname(String uname) {
this.uname = uname;
} public String getUpwd() {
return upwd;
} public void setUpwd(String upwd) {
this.upwd = upwd;
}
}
测试类:ReflectAction.java
package com.xfwl.reflect; import java.lang.reflect.Method; public class ReflectAction {
/**
* @param args
*/
public static void main(String[] args) {
UserBean jack=null;
UserBean tom=null;
Class tomC=null;
try{
jack=(UserBean)Class.forName("com.xfwl.reflect.UserBean").newInstance();
//jack.logIn(); tomC=Class.forName("com.xfwl.reflect.UserBean");
tom=(UserBean) tomC.newInstance();
Method[] methods = tomC.getDeclaredMethods();
for (Method method : methods){
if("logOut".equals(method.getName())){
method=tomC.getDeclaredMethod(method.getName(),UserBean.class);
System.out.println(method);
method.invoke(tomC.newInstance(),tom);
}
}
}catch(Exception e){ } } }
运行结果:没有执行:logOut()
修改:
public void logOut(UserBean user){
System.out.println("用户退出:uname="+this.getUname()+",upwd="+this.getUpwd());
}
即可执行:logOut()