一、反射是什么?反射有什么用?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能:
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理。
二、怎么使用反射?
1、获得Class类的实例化对象
注意这里可能并不懂Class
类,我截取了一段百度上的解释:
具体内容可以自己百度,这里就不详细解释了。
获取Class类的实例化对象的三种方法:
1、Object
类提供了一个返回Class
类对象的方法:public final Class<?> getClass()
,这种方法并不常用。
2、利用类.class
获得,多用在Hibernate
上。
3、利用Class
类的静态方法获得:public static Class<?> forName(String className) throws ClassNotFoundException
,这种方法最常用。
2、利用反射实例化对象
如果获得了Class
对象后,我们就可以用Class
类定义的newInstance()
方法默认调用类之中的无参构造方法(这里要求类之中必须有无参构造方法)进行操作。注意这里用到的newInstance()
方法在新版本的java中已经被弃用了
示例:
package com.jiayifan.demo;
class Student {
public Student() {
System.out.println("Student类的构造方法");
}
public String toString() {
return "Student类的toString()方法";
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.jiayifan.demo.Student");
@SuppressWarnings("deprecation")
Object obj = cls.newInstance();
//相当于Object obj = new Student();
System.out.println(obj);
}
}
运行截图:
明显上面的方法是不够的,我们这时候就需要使用Class
类里定义的可以获得一个类的构造方法的操作:
- 获得类中的全部构造方法:
public Constructor<?>[] getConstructors() throws SecurityException
- 获得类中指定参数的构造方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException,
SecurityException
示例——获得全部构造方法:
package com.jiayifan.demo;
import java.lang.reflect.Constructor;
public class ReflectStringDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("java.lang.String");
Constructor<?>[] cons = cls.getConstructors();
for(int i=0;i<cons.length;i++) {
System.out.println(cons[i]);
}
}
}
运行截图:
示例——获得指定的构造方法:
package com.jiayifan.demo;
import java.lang.reflect.Constructor;
class Student {
private String name;
private Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String toString() {
return "姓名:" + name + " 年龄:" + age;
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.jiayifan.demo.Student");
Constructor<?> cons = cls.getConstructor(String.class, Integer.class);
Object obj = cons.newInstance("李华", 19);
//相当于Object obj = new Student("李华", 19);
System.out.println(obj);
}
}
运行截图:
3、调用类中的方法和属性(这里如果加了Declared,表示包括继承,不加的话,表示不包括继承)
方法:
(1)获得全部方法
public Method[] getMethods()//该方法获得包括继承的全部方法
throws SecurityException
public Method[] getDeclaredMethods()//该方法获得不包括继承的全部方法
throws SecurityException
(2)获得指定的方法
public Method getMethod(String name,
Class<?>... parameterTypes)
throws NoSuchMethodException,
SecurityException
public Method getDeclaredMethod(String name,
Class<?>... parameterTypes)
throws NoSuchMethodException,
SecurityException
因为示例基本都是相同的写法,所以这里就只展示一个使用特定方法的例子:
package com.jiayifan.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.jiayifan.demo.Student");
@SuppressWarnings("deprecation")
Object obj = cls.newInstance();//注意如果要调用方法,需要先实例化对象
Method setMethod = cls.getMethod("setName", String.class);
Method getMethod = cls.getMethod("getName");
setMethod.invoke(obj, "lili");//这里必须提供实例化的对象作为参数
System.out.println(getMethod.invoke(obj));
}
}
运行截图:
调用属性的方法和调用方法的方法基本类似,所以这里就不演示了,如果需要相关的函数,可以到:戳我一下
调用属性和方法的时候还是有一点需要注意,就是如果调用的私有的属性和方法,我们需要在操作之前,用setAccessible()
方法,将封装取消,这样就可以使用私有的方法和属性。