什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。
测试类
public class Person {
private Integer id;
private String name;
private Integer age;
private String address;
//有参构造
public Person(){}
//无参构造
public Person(Integer id, String name, Integer age, String address) {
super();
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
//重写toString
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age
+ ", address=" + address + "]";
}
//静态无参方法
public static void show(){
System.out.println("调用无参静态方法");
}
//静态有参方法
public static String showTwo(String mes){
return mes;
}
}
Class
对象
Class
类的实例表示正在运行的 Java
应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class
对象的一个类,所有具有相同元素类型和维数的数组都共享该Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和double)
和关键字 void
也表示为 Class
对象。 Class
没有公共构造方法。Class 对象是在加载类时由 Java
虚拟机以及通过调用类加载器中的defineClass
方法自动构造的。
在Java中,每个class都有一个相应的Class
对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class
对象,用于表示这个类的类型信息。Class
类不是我们认为创建的,是由java虚拟机,在我们生成.class
文件的时候创建的。以下是获取Class
对象三种方法:
//通过类全名获取Class对象
Class<?> clazz = Class.forName("java.lang.String");
//通过对象获取类的Class对象
Person obj=new Person();
Class<?> clazz = obj.getClass();
//通过类名获取类的Class对象
Class<?> clazz = Person.class;
获取对象成员
//通过类名获取类的Class对象
//Class<?> clazz = Person.class;
Class<?> clazz = Class.forName("com.yzx.reflect.Person");
//通过Class对象获取类的全部方法
Method[] methods = clazz.getDeclaredMethods();
for(Method m : methods){
System.out.println(m);
}
//获取指定方法(无参),参数为方法名称,参数类型Class数组
Method method1 = clazz.getDeclaredMethod("getName", new Class[]{});
System.out.println(method1);
//获取指定方法(有参)
Method method2 = clazz.getDeclaredMethod("setName", new Class[]{String.class});
System.out.println(method2);
//获取全部属性
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
System.out.println(f);
}
//获取指定属性
Field field = clazz.getDeclaredField("address");
System.out.println(field);
//获取全构造器
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for(Constructor c : constructors){
System.out.println(c);
}
//获取指定构造器(无参)
Constructor<?> constructor1 = clazz.getDeclaredConstructor(new Class[]{});
System.out.println(constructor1);
//获取指定构造器(有参)
Constructor<?> constructor2 = clazz.getDeclaredConstructor(new Class[]{Integer.class,String.class,Integer.class,String.class});
System.out.println(constructor2);
创建对象
Class<?> clazz = Class.forName("com.yzx.reflect.Person");
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{});
//通过构造器创建对象(无参)
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);
//通过构造器创建对象(有参)
Constructor<?> constructor1 = clazz.getDeclaredConstructor(new Class[]{Integer.class,String.class,Integer.class,String.class});
Object instance2 = constructor1.newInstance(new Object[]{1,"李四",23,"北京"});
System.out.println(instance2);
方法调用
Class<?> clazz = Class.forName("com.yzx.reflect.Person");
//获取类的构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{});
//通过构造器创建对象
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);
//获取指定方法
Method setName = clazz.getDeclaredMethod("setName", new Class[]{String.class});
//调用方法并传值
setName.invoke(instance, new Object[]{"李四"});
System.out.println(instance);
//获取指定方法
Method getName = clazz.getDeclaredMethod("getName", new Class[]{});
//调用方法并传值
Object invoke = getName.invoke(instance, new Object[]{});
System.out.println(invoke);
//调用无参静态方法
Method show = clazz.getDeclaredMethod("show", new Class[]{});
show.invoke(null, null);
//调用有参静态方法
Method showTwoMethod = clazz.getDeclaredMethod("showTwo", new Class[]{String.class});
Object ret = showTwoMethod.invoke(instance, new Object[]{"调用有参静态方法"});
System.out.println(ret);
私有属性赋值
Class<?> clazz = Class.forName("com.yzx.reflect.Person");
//获取类的构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{});
//通过构造器创建对象
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);
//获取属性
Field nameField = clazz.getDeclaredField("name");
//获取属性类型
Class<?> type = nameField .getType();
System.out.println(type);
//私有属性设置为true
nameField.setAccessible(true);
nameField.set(instance, "李四");
System.out.println(nameField.get(instance));
拷贝对象
public static void main(String[] args) throws Exception {
Person p=new Person();
p.setName("李四");
Object newObj=copyObject(p);
System.out.println(newObj);
}
public static Object copyObject(Object obj)throws Exception{
Class<? extends Object> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
Constructor<? extends Object> constructor = clazz.getConstructor(new Class[]{});
//创建一个对象
Object instance = constructor.newInstance(new Object[]{});
for(Field f:fields){
//获取属性名
String fName=f.getName();
//获取属性类型
Class<?> type = f.getType();
//获取属性对应的get、set方法
String setMethodName="set"+fName.substring(0,1).toUpperCase()+fName.substring(1);
String getMethodName="get"+fName.substring(0,1).toUpperCase()+fName.substring(1);
//获得get方法
Method gMethod = clazz.getDeclaredMethod(getMethodName, null);
Object gResult = gMethod.invoke(obj, null);
//获得set方法
Method sMethod = clazz.getDeclaredMethod(setMethodName,new Class[]{gMethod.getReturnType()});
sMethod.invoke(instance, new Object[]{gResult});
}
return instance;
}
反射是一种强大的工具,但也存在一些不足。一个主要的缺点是对性能有影响。使用反射基本上是一种解释操作,您可以告诉JVM您希望做什么并且它满足您的要求。这类操作总是慢于直接执行相同的操作。
相关文章
引入反射 Java反射机制详解 Java反射机制 深入解析Java反射