实践
通过反射实例化
package com.reflectionTest;
public class People {
private String name = "";
private int year = 0;
private People(){}
private People(String name,int year){
this.name = name;
this.year = year;
}
public void say(){
System.out.println("Hello,My name is "+name +",it is a Non-parameter method");
}
public void eat(String food){
System.out.println(name +"eat "+food+",it is a Method with parameters");
}
public static void run(){
System.out.println("it is a static method");
}
}
package com.reflectionTest;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
try{
Class<?> clz = Class.forName("com.reflectionTest.People");
Constructor<?> cons = clz.getConstructor();
Object obj1 = cons.newInstance();
//通过无参构造函数进行创建
Constructor<?> constructor = clz.getDeclaredConstructor(String.class,int.class);
Object obj2 = constructor.newInstance(new Object[]{"小华",12});
//通过带参数构造函数进行创建
Method method = clz.getDeclaredMethod("say");
method.invoke(obj1);//把实例化作为第一个参数传入
//调用无参数的非静态方法
Method method2 = clz.getDeclaredMethod("eat",String.class);
method2.invoke(obj1,new Object[]{"小明"});//第一个参数为实例,之后的参数为具体参数值
//调用带参数的非静态方法
}catch (Exception e){
e.printStackTrace();
}
}
}
调用私有方法
package com.reflectionTest;
public class People {
private String name;
public People(String name){
this.name = name;
}
/**
* 私有方法
*/
private void println(){
System.out.println("it is a private method,这个人名叫:"+name);
}
/**
* 有返回值的私有方法
* @return
*/
private String getName(){
return name;
}
/**
* 有一个传参的私有方法
* @param name
*/
private void setName(String name){
this.name = name;
}
/**
* 有多个传参的私有方法
* @param name
*/
private void setInfo(String name,int age){
this.name = name;
}
/**
* 静态私有方法
*/
private static void run(){
System.out.println("it is a private and static method");
}
}
package com.reflectionTest;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception{
People people = new People("小明");
//有返回值的无参方法
Method getNameMethod = people.getClass().getDeclaredMethod("getName");
getNameMethod.setAccessible(true);
String name = (String) getNameMethod.invoke(people);
System.out.println("获取带参私有函数的返回值:"+name);
//调用带参数的方法
Method setNameMethod = people.getClass().getDeclaredMethod("setName",String.class);
setNameMethod.setAccessible(true);
setNameMethod.invoke(people,"小红");
//调用多个参数的方法
Method setInfoMethod = people.getClass().getDeclaredMethod("setInfo",String.class,int.class);
setInfoMethod.setAccessible(true);
setInfoMethod.invoke(people,"小红",12);
//无参无返回值的方法
Method printMethod= people.getClass().getDeclaredMethod("println");
printMethod.setAccessible(true);
printMethod.invoke(people);
//静态方法
Class<?> clz = Class.forName("com.reflectionTest.People");
Method method3 = clz.getDeclaredMethod("run");
method3.setAccessible(true);//将作为域设置为可见(也就是public)
method3.invoke(null);//和调用非静态方法的区别在于不用利用反射实例化,第一个参数直接传入null即可。
}
}
获取带参私有函数的返回值:小明 it is a private method,这个人名叫:小红 it is a private and static method
私有方法传参为数组或List的处理方法
package com.reflectionTest;
import java.util.List;
public class People {
private String name;
private People[] mChild;
public People(String name){
this.name = name;
}
public String getName(){
return name;
}
private void setChildrenArray(People[] children){
this.mChild = children;
}
private void setChildrenList(List<People> children){
this.mChild = (People[]) children.toArray();
}
public People[] getChildArray(){
return mChild;
}
}
package com.reflectionTest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) throws Exception{
People people = new People("小明");
People[] child = new People[2];
child[0] = new People("小红");
child[1] = new People("小刚");
//数组的传参处理
Method setChildrenArrayMethod = people.getClass().getDeclaredMethod("setChildrenArray",People[].class);
setChildrenArrayMethod.setAccessible(true);
setChildrenArrayMethod.invoke(people, (Object) child);
System.out.println("设置数组后获取到的内容如下:");
for (People p:people.getChildArray()){
System.out.println(p.getName());
}
//ArrayList/List的处理方法
Method setChildrenListMethod = people.getClass().getDeclaredMethod("setChildrenList", List.class);
setChildrenListMethod.setAccessible(true);
setChildrenListMethod.invoke(people, Arrays.asList(child));
System.out.println("设置List后获取到的内容如下:");
for (People p:people.getChildArray()){
System.out.println(p.getName());
}
}
}
参考:https://segmentfault.com/q/1010000018762976/a-1020000018765152
简述:传参为List类似时,无论元素类型是什么,直接传参List.class即可,泛型参数在编译后会被擦除掉,无论List里面是String还是什么别的东西都不会影响获取到那个method,在invoke的时候传的参数对不上的话才会产生异常。
获取及修改私有变量
package com.hxw.test;
public class People {
private String name = "未名";
private static String type = "人类";//静态私有变量
public People(){}
public People(String name){
this.name = name;
}
public void println(){
System.out.println("我的名字叫:"+name);
}
}
import com.hxw.test.People;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception{
People people = new People("小明");
Class clazz = Class.forName("com.hxw.test.People");
Field nameF = clazz.getDeclaredField("name");
nameF.setAccessible(true);//将私有变量设置为可访问
//获取私有变量的值
String name = (String) nameF.get(people);
System.out.println(name);
//这里获取到实例People的私有变量,打印的结果为:小明
//修改私有变量
nameF.set(people,"小红");
people.println();//已将People的私有变量name修改为:小红
//获取私有静态变量
Field typeF = People.class.getDeclaredField("type");
typeF.setAccessible(true);//将私有变量设置为可访问
String type = (String) typeF.get(null);//获取静态变量传参直接为null即可
System.out.println(type);
//修改私有静态变量
typeF.set(null,"狗");
System.out.println((String) typeF.get(null));
}
}
小明 我的名字叫:小红 人类 狗
API
反射机制的相关类
与Java反射相关的类如下:
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
获得类相关的方法 | 方法 | 用途 | | —- | —- | | asSubclass(Class clazz) | 把传递的类的对象转换成代表其子类的对象 | | Cast | 把对象转换成代表类或是接口的对象 | | getClassLoader() | 获得类的加载器 | | getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 | | getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 | | forName(String className) | 根据类名返回类的对象 | | getName() | 获得类的完整路径名字 | | newInstance() | 创建类的实例 | | getPackage() | 获得类的包 | | getSimpleName() | 获得类的名字 | | getSuperclass() | 获得当前类继承的父类的名字 | | getInterfaces() | 获得当前类实现的类或是接口 |
- 获得类中属性相关的方法 | 方法 | 用途 | | —- | —- | | getField(String name) | 获得某个公有的属性对象 | | getFields() | 获得所有公有的属性对象 | | getDeclaredField(String name) | 获得某个属性对象 | | getDeclaredFields() | 获得所有属性对象 |
- 获得类中注解相关的方法 | 方法 | 用途 | | —- | —- | | getAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的公有注解对象 | | getAnnotations() | 返回该类所有的公有注解对象 | | getDeclaredAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的所有注解对象 | | getDeclaredAnnotations() | 返回该类所有的注解对象 |
- 获得类中构造器相关的方法 | 方法 | 用途 | | —- | —- | | getConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 | | getConstructors() | 获得该类的所有公有构造方法 | | getDeclaredConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 | | getDeclaredConstructors() | 获得该类所有构造方法 |
- 获得类中方法相关的方法 | 方法 | 用途 | | —- | —- | | getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 | | getMethods() | 获得该类所有公有的方法 | | getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法 | | getDeclaredMethods() | 获得该类所有方法 |
- 类中其他重要的方法 | 方法 | 用途 | | —- | —- | | isAnnotation() | 如果是注解类型则返回true | | isAnnotationPresent(Class<? extends Annotation> annotationClass) | 如果是指定类型注解类型则返回true | | isAnonymousClass() | 如果是匿名类则返回true | | isArray() | 如果是一个数组类则返回true | | isEnum() | 如果是枚举类则返回true | | isInstance(Object obj) | 如果obj是该类的实例则返回true | | isInterface() | 如果是接口类则返回true | | isLocalClass() | 如果是局部类则返回true | | isMemberClass() | 如果是内部类则返回true |
Field类
Field代表类的成员变量(成员变量也称为类的属性)。
方法 | 用途 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
Method类
Method代表类的方法。
方法 | 用途 |
---|---|
invoke(Object obj, Object… args) | 传递object对象及参数调用该对象对应的方法 |
Constructor类
Constructor代表类的构造方法。
方法 | 用途 |
---|---|
newInstance(Object… initargs) | 根据传递的参数创建类的对象 |