一、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想分析一个类,必须先要获取到该类的字节码文件对象。而分析使用的就是Class类中的方法.所以先要获取到字节码文件对应的Class类型的对象.
如图所示演示了反射的整个过程(画了很久的图,我认为描述清楚了)
接下来用代码记录反射的常用方法:
先建立两个接口(后面有用):
MyInterface.java
public interface MyInterface {
void interfaceMethod();
}
MyInterface2.java
public interface MyInterface2 {
void interfaceMethod();
}
再创建一个学生类,属性为id,姓名和性别,并实现有参构造方法,无参构造方法,静态方法。
Student.java
public class Student implements MyInterface {
private int id;
private String name;
public String sex;
public Student() {
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void staticmethon(){ //静态方法
System.out.println("static methods..");
}
@Override
public void interfaceMethod() {//实现MyInterface接口
System.out.println("interfaceMethon");
}
}
二、反射常用方法
1、Class.forName()方法(本文剩余的方法介绍都得先用这个方法获取反射入口)
最重要的是先获取反射入口Class对象(有三种方式),但这里用最普遍的Class.forName()方法,注意要写上抛出ClassNotFoundException异常
ReflectDemo.java
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");//获取反射入口,注意forName内要写完整的类路径
System.out.println(refelct);
}
}
2、通过反射获取类的公共方法(本类,父类和接口的非private方法)
refelect.getMethods():返回Method数组
import java.lang.reflect.Method;
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Method[] methods=refelct.getMethods();
for(Method method:methods){
System.out.println(method);
}
}
}
输出结果:
拿到了包括当前类和其父类Object类的所有公共方法以及实现了接口的方法interfaceMethon()
就拿第一个public java.lang.String Student.getName() 和Student.java中的public String getName()相比,显然通过反射拿到的是很完整的
3、通过反射获取本类的所有非private修饰的方法(本类的所有方法,不包括父类,但包括接口)
refelect.getDeclaredMethods():返回Method数组
import java.lang.reflect.Method;
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Method[] methods=refelct.getDeclaredMethods();
for(Method method:methods){
System.out.println(method);
}
}
}
输出结果:
最后一行是接口
4、通过反射获取类的接口
reflect.getInterfaces():返回接口名数组
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Class<?>[]interfaces=refelct.getInterfaces();
for(Class<?> inter:interfaces){
System.out.println(inter);
}
}
}
输出结果:
5、通过反射获取类的父类
refelct.getSuperclass():返回父类
由于java是单继承,所以返回值不是数组
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Class<?>superclass=refelct.getSuperclass();
System.out.println(superclass);
}
}
输出结果:
任何一个类都继承Object类,所以会输出Object类
6、通过反射获取类的所有构造方法
refelct.getConstructors():返回类所有构造方法,返回值为数组
import java.lang.reflect.Constructor;
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Constructor<?>[] constructors=refelct.getConstructors();
for (Constructor<?> constructor:constructors){
System.out.println(constructor);
}
}
}
输出结果:一个无参构造,一个有参构造
7、通过反射获取类的所有公共属性(不包括Private修饰的属性)
refelct.getFields():返回Field类型数组
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Field[] fields=refelct.getFields();
for (Field field:fields){
System.out.println(field);
}
}
}
输出结果:(注意private修饰的属性无法拿到,代码中studnet的id和name都是private因此没有输出,只输出了public修饰的sex属性)
8、通过反射获取本类的所有属性(包括Private修饰的属性,不包括父类和父接口)
refelct.getDeclaredFields():返回Field类型数组
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException {
Class<?> refelct=Class.forName("Student");
Field[] fields=refelct.getDeclaredFields();
for (Field field:fields){
System.out.println(field);
}
}
}
输出结果:
很明显private的属性id和name都输出了
9、 通过反射获取类的实例对象(和普通的new一个对象功能类似)
refelct.newInstance();
需要设置可能会抛出的两个异常:IllegalAccessException, InstantiationException
public class ReflectDemo {
public static void main(String[]args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> refelct=Class.forName("Student");
Object student=refelct.newInstance();//获得的是个Object类对象
Student student1=(Student)student;//将Object对象向下转型为Student类对象
student1.interfaceMethod();//验证:通过调用Student类的静态方法打印输出
}
}
输出内容:
可以看出这种方法和使用Student student=new student();student.interfaceMethod();起到了相同的效果