反射
反射
一、什么是反射
反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。
Java反射机制主要提供了以下功能:
在运行时构造任意一个类的对象
在运行时获取或者修改任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法(属性)
二、获取Class类
获取Class对象的三种方式
1. 通过类名获取 类名.class
2. 通过对象获取 对象名.getClass()
3. 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)
使用 Class 类的 forName 静态方法
public static Class<?> forName(String className)
直接获取某一个对象的 class
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;
调用某个对象的 getClass() 方法
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();
三、创建实例
通过反射来生成对象主要有两种方式。
使用Class对象的newInstance()方法来创建Class对象对应类的实例。
Class<?> c = String.class;
Object str = c.newInstance();
先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这
种方法可以用指定的构造器构造类的实例。
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);
四、获取构造方法
Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的public构造函数(包括父类)
Constructor[] getConstructors() -- 获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(包括私有)
Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)
获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法可以创建一个对象实例:
public T newInstance(Object ... initargs)
五、调用方法
获得方法信息的方法
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法
Method[] getMethods() -- 获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods() -- 获得类声明的所有方法
当我们从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。invoke 方法的原型为:
public Object invoke(Object obj, Object... args)
六、利用反射创建数组
数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference 其中的Array类为
java.lang.reflect.Array类。
我们通过Array.newInstance()创建数组对象,它的原型是:
public static Object newInstance(Class<?> componentType, int length);
六、获取泛型信息
当我们对一个泛型类进行反射时,需要的到泛型中的真实数据类型,来完成如json反序列化的操作。此时需要通过Type 体系来完成。Type 接口包含了一个实现类(Class)和四个实现接口,他们分别是:
TypeVariable
泛型类型变量。可以泛型上下限等信息;
ParameterizedType
具体的泛型类型,可以获得元数据中泛型签名类型(泛型真实类型)
GenericArrayType
当需要描述的类型是泛型类的数组时,比如List[],Map[],此接口会作为Type的实现。
WildcardType
通配符泛型,获得上下限信息;
反射demo源码
```
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflect {
public static void main(String[] args) {
System.out.println("--------获取class类-----------");
Person person =new Person();
Class clazz = person.getClass();
System.out.println(clazz);
Class clazz1 = Person.class;
System.out.println(clazz1);
try {
Class clazz2 = Class.forName("com.example.Person");
System.out.println(clazz2);
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("---------获取构造方法-----------");
getConstractor(clazz);
System.out.println("------获取对象方法---------");
getMethod(clazz);
System.out.println("---------构造方法创建对象-------------");
//创建Person对象
try {
Constructor con = clazz.getDeclaredConstructor();
//无参构造方法
Object object = con.newInstance();
System.out.println(object.toString());
//指定参数构造方法
Constructor con1 = clazz.getDeclaredConstructor(String.class, int.class);
Object object1 = con1.newInstance("张三", 18);
System.out.println(object1.toString());
System.out.println("-------执行方法---------");
try {
Method m = clazz.getDeclaredMethod("getName");
//执行方法
Object name = m.invoke(object1);
System.out.println(name);
//执行私有方法需要设置setAccessible
Method m1 = clazz.getDeclaredMethod("toStr");
m1.setAccessible(true);
Object obj = m1.invoke(object1);
System.out.println(obj);
//执行完毕关闭
m1.setAccessible(false);
}catch (NoSuchMethodException e){
e.printStackTrace();
}
}catch (NoSuchMethodException | InstantiationException |
IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
private static void getConstractor(Class clazz) {
//获取所有公有构造方法
Constructor[] cons = clazz.getConstructors();
for (Constructor constructor : cons) {
System.out.println(constructor);
}
System.out.println("------------------");
try {
//获取指定参数的公有构造方法
Constructor con = clazz.getConstructor(new Class[]{String.class, int.class});
System.out.println(con);
}catch (NoSuchMethodException e) {
e.printStackTrace();
}
System.out.println("------------------");
//获取所有构造方法
Constructor[] declardcons = clazz.getDeclaredConstructors();
for (Constructor constructor : declardcons) {
System.out.println(constructor);
}
System.out.println("------------------");
try {
//获取指定参数的所有构造方法
Constructor con = clazz.getDeclaredConstructor();
System.out.println(con);
}catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private static void getMethod(Class clazz){
//获取所有公有方法包含父类
Method[] methods = clazz.getMethods();
for (Method m:methods){
System.out.println(m);
}
System.out.println("-----------------");
try {
//获取指定名称的公有方法
Method method = clazz.getMethod("getName");
System.out.println(method);
}catch (NoSuchMethodException e){
e.printStackTrace();
}
System.out.println("------------------");
//获取类的所有方法不包含父类
Method[] methods1 = clazz.getDeclaredMethods();
for (Method m:methods1){
System.out.println(m);
}
System.out.println("------------------");
try {
Method m = clazz.getDeclaredMethod("toStr");
System.out.println(m);
}catch (NoSuchMethodException e){
e.printStackTrace();
}
}
}
class Person {
private Stringname;
private int age;
public Person() {
}
private Person(int age) {
this.age = age;
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public StringgetName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public StringtoString() {
return "Person{" +
"name='" +name +'\'' +
", age=" +age +
'}';
}
private StringtoStr() {
return "Person{" +
"name='" +name +'\'' +
", age=" +age +
'}';
}
}
```