反射
JAVA反射机制是在运行状态中对于
任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射的作用
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
Class类
反射操作的源头类:java.lang.Class
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
枚举是一种类,注释是一种接口。
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象
- 用于获取与类相关的各种信息, 提供了获取类信息的相关方法
- Class类继承自Object类
反射操作
Class类对象实例化
- 调用Object类中的getClass()方法,但如果要使用此类操作必须有实例化对象
import java.util.*;
public class Test6 {
public static void main(String[] args) {
Date date = new Date(); //实例化对象
Class<? extends Date> class1 = date.getClass(); //Class对象
System.out.println(class1.getName()); //获得对象所在类的对象
}
}
2. 使用"类.class"取得,不需要指定类的实例化对象取得
import java.util.*;
public class Test6 {
public static void main(String[] args) {
Class<? extends Date> class1 = Date.class;
System.out.println(class1.getName());
}
}
- 调用Class类提供的方法:public static Class<?> forName(String className) throws ClassNotFoundException
用此方法只需要定义一个具体的名称就可以取得反射操作类对象,前提是此类确定存在,否则抛出"ClassNotFoundException"异常
import java.util.*;
public class Test6 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cla = Class.forName("java.util.Date");
System.out.println(cla.getName());
}
}
反射实例化对象
Class类的常用方法
方法 | 描述 |
---|---|
public static Class<?> forName(String className) throwsClassNotFoundException | 通过字符串设置的类名称实例化Class对象 |
public T newInstance() throws InstiationException,IllegalAccessException | 反射实例化对象 |
可以通过newInstance()方法利用反射实现Class类包装类型的对象实例化操作(类要提供无参构造方法)
package classes;
import java.util.*;
public class Test6 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class<?> cla = Class.forName("classes.Book");
Object newInstance = cla.newInstance();
Book book = (Book) newInstance;
System.out.println(book);
}
}
class Book{
public Book(){
System.out.println("无参构造方法");
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "java";
}
}
利用反射机制实例化对象可以实现更好的解耦合操作
使用反射调用构造
当类中只提供有参构造方法时,可以通过java.lang.reflect.Constructor类来实现对象的实例化操作
类中的构造方法
方法 | 描述 |
---|---|
public Constructor<?>[] getConstructors() throws SecurityException | 取得所有的构造方法 |
public Constructor getConstructor() throws NoSuchMethodException,SecurityException | 取得指定参数类型的构造方法 |
public T newInstance(Object… initargs) throws InstantiationException,IllegalArgumentException,InvocationTargetException | 调用指定参数的构造方法实例化对象 |
通过Class类找到指定参数类型的构造方法,在利用Constructor类的newInstance()方法传入实例化对象所需要的参数可以实现指定参数的构造方法调用
反射调用方法
方法 | 描述 |
---|---|
public Method getMethod(String name,Class<?>… parameterTypes) throw NoSuchMethodException,SecurityException | 取得类中指定方法名称与参数类型的方法 |
public Object invoke(Object obj,Object… args) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException | 反射调用方法并且传递执行方法所需要的参数数据 |
在任何情况下,调用类中的普通方法要产生类的实例化对象才可以
反射调用成员
方法 | 描述 |
---|---|
public Field[] getDeclaredFields() throws SecurityException | 取得本类中定义的全部成员 |
public Field getDeclared | 取得本类指定名称的成员 |
package classes;
import java.lang.reflect.Field;
import java.util.*;
public class Test6 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
Class<?> cls = Class.forName("classes.Book");
Object obj = cls.newInstance();//实例化对象
Field declaredField = cls.getDeclaredField("title");//取得类中的title属性
declaredField.setAccessible(true); //取消封装
declaredField.set(obj, "java");
System.out.println(declaredField.get(obj));
}
}
class Book{
private String title;
}