一 Java 反射概述
反射是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
Java反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
生成动态代理
二 Java 反射实例
1.创建一个Person类。
package com.fengxunxinxi.reflection;
/**
* Person calss
* @author mofengyu
*
* @date 2019/10/26
*/
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println(".....");
}
public void display(String nation){
System.out.println(nation);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.运用反射创建Person类对象,执行操作
package com.fengxunxinxi.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Test class
* @author mofengyu
*
* @date 2019/10/26
*/
public class Test {
public static void main(String[] args) throws Exception{
Class clazz=Person.class;
/**
* 通过clazz的运行时类Person类创建对象
*/
Person person=(Person)clazz.newInstance();
System.out.println(person);
/**
* 获取name属性
*/
Field field=clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(person,"mofengyu");
System.out.println(person);
/**
* 获取运行时类的方法
*/
Method show=clazz.getMethod("show");
/**
* 执行方法
*/
show.invoke(person);
Method display=clazz.getMethod("display",String.class);
/**
* 执行Person类中的display方法
*/
display.invoke(person,"CN");
}
}
3.测试结果
三 Class类
某个类的属性、方法和构造器、某个类实现了那些接口。对于类而言,JRE都为其保留一个不变的Class类型对象。一个Class类包含了特定类的有关信息。
1.Class本身也是一个类
2.Class对象只能由系统建立对象
3.一个类在JVM只会有一个Class实例
4.一个Class对象对应的是一个加载到JVM中的一个.classs文件
5.每个类实例都会记得自己是由那个Class实例生成的
6.通过Class可以完整地得到一个类中的完整结构
java.lang.Class是反射的源头,创建一个类,通过编译(javac.exe),生成对应的.class文件。之后通过使用java.exe加载(JVM的类加载器加载此.class文件),此.class文件加载到内存后,就是一个运行时类,存在缓冲区,那么这个运行时类本身就是一个Class实例。
获取Class实例的四种方法
/**
* 获取Class实例的三种方法
*/
/**
* 调用运行时类的class属性
*/
Class clazz1=Person.class;
System.out.println(clazz1.getName());
/**
* 通过运行时类的对象获取
*/
Person person=new Person();
Class clazz2=person.getClass();
System.out.println(clazz2.getName());
/**
* 通过Class的静态方法获取
*/
String className="com.fengxunxinxi.reflection.Person";
Class clazz3=Class.forName(className);
System.out.println(clazz3.getName());
/**
* 通过类的加载器
*/
ClassLoader classLoader=this.getClass().getClassLoader();
Class clazz4=classLoader.loadClass(className);
System.out.println(clazz4.getName());
四 ClassLoader
类加载器是用来把类(Class)装载进内存的。JVM规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定义加载器(user-defined class loader)。JVM运行时会产生三个类加载器组成的初始化加载器层次。
当程序主动使用这个类时,如果该类还未被加载到内存中,则系统会进行如下三个步骤来对该类进行初始化。
五 Class对象
1.创建类的对象:调用Class对象的newInstance()方法
1)类必须有一个无参数的构造器
2)类的构造器访问权限要足够
package com.fengxunxinxi.reflection;
/**
* TestConstroutor class
* @author mofengyu
*
* @date 2019/10/31
*/
public class TestConstroutor {
public static void main(String[] args) throws Exception{
String className="com.fengxunxinxi.reflection.Person";
Class clazz=Class.forName(className);
Person person=(Person)clazz.newInstance();
System.out.println(person);
}
}
2.获取类的相关属性
package com.fengxunxinxi.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestField {
public static void main(String[] args) {
Class clazz=Person.class;
/**
* getFields():只能获取到运行时类及父类中声明为pubilc的属性
*/
Field[] fields=clazz.getFields();
for(int i=0;i<fields.length;i++){
System.out.println(fields[i]);
}
System.out.println();
/**
* 获取运行时类的所有属性
*/
Field[] fields1=clazz.getDeclaredFields();
for(Field field:fields1){
/**
* 获取权限修饰符
*/
int s=field.getModifiers();
String str= Modifier.toString(s);
System.out.println(str);
/**
* 获取返回值
*/
Class type=field.getType();
System.out.println(type.getName());
System.out.println(field);
}
}
}
3.获取方法
package com.fengxunxinxi.reflection;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* TestMethod class
* @author mofengyu
*
* @date 2019/10/31
*/
public class TestMethod {
public static void main(String[] args) {
Class clazz=Person.class;
/**
* getMethods():获取运行时类及父类中声明为public的方法
*/
Method[] methods=clazz.getMethods();
for(Method method:methods){
System.out.println(method);
}
System.out.println();
/**
* getDeclaredMethods():获取运行时类本身声明的所有方法
*/
Method[] methods1=clazz.getDeclaredMethods();
for(Method m:methods1){
/**
* 获取注解
*/
Annotation[] annotations=m.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
/**
* 获取权限修饰符
*/
String str=Modifier.toString(m.getModifiers());
System.out.println(str);
/**
* 获取返回值类型
*/
Class returnType=m.getReturnType();
System.out.println(returnType.toString());
/**
* 获取方法名
*/
System.out.println(m.getName());
/**
* 获取形参列表
*/
Class[] params=m.getParameterTypes();
for(Class param:params){
System.out.println(param.getName());
}
/**
* 获取异常
*/
Class[] ex=m.getExceptionTypes();
for(Class e:ex){
System.out.println(e.getName());
}
System.out.println(m);
}
}
}
4.获取构造器
public static void main(String[] args) throws Exception{
String className="com.fengxunxinxi.reflection.Person";
Class clazz=Class.forName(className);
Constructor[] constructors=clazz.getConstructors();
for(Constructor constructor:constructors){
System.out.println(constructor);
}
}
5.获取父类
public static void main(String[] args) {
Class clazz=Person.class;
/**
* 获取运行时类的父类
*/
Class superClass=clazz.getSuperclass();
System.out.println(superClass);
/**
* 获取带泛型的父类
*/
Type type=clazz.getGenericSuperclass();
System.out.println(type);
/**
* 获取父类的泛型
*/
ParameterizedType parameterizedType=(ParameterizedType)type;
Type[] types=parameterizedType.getActualTypeArguments();
System.out.println(((Class)types[0]).getName());
}
6.获取其它相关信息
public static void main(String[] args) {
Class clazz=Person.class;
/**
* 获取实现的接口
*/
Class[] interfaces=clazz.getInterfaces();
for(Class in:interfaces){
System.out.println(in.getName());
}
/**
* 获取所在包
*/
Package p=clazz.getPackage();
System.out.println(p);
/**
* 获取注解
*/
Annotation[] annotations=clazz.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
}
7.获取指定属性并赋值
public static void main(String[] args) throws Exception{
Class clazz=Person.class;
/**
* 获取指定属性
*/
Field name=clazz.getField("name");
/**
* 创建运行时对象
*/
Person person=(Person)clazz.newInstance();
System.out.println(person);
/**
* 运行时类指定属性赋值
*/
name.set(person,"Jerry");
System.out.println(person);
Field age=clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(person,18);
System.out.println(person);
}
7.获取指定方法并调用
public static void main(String[] args) throws Exception{
Class clazz=Person.class;
/**
* 获取指定方法,getMethod()获取声明为public的方法
*/
Method show=clazz.getMethod("show");
Person person=(Person)clazz.newInstance();
Object returnValue=show.invoke(person);
System.out.println(returnValue);
/**
* 获取toString()方法
*/
Method toString=clazz.getMethod("toString");
Object returnValue1=toString.invoke(person);
System.out.println(returnValue1);
Method info=clazz.getMethod("info");
/**
* 调用静态方法
*/
Object returnValue2=info.invoke(Person.class);
System.out.println(returnValue2);
/**
* 获取声明的方法
*/
Method display=clazz.getDeclaredMethod("display",String.class,Integer.class);
display.setAccessible(true);
Object returnValue4=display.invoke(person,"CHN",1);
System.out.println(returnValue4);
}
8.调用指定构造函数
public static void main(String[] args) throws Exception{
String className="com.fengxunxinxi.reflection.Person";
Class clazz=Class.forName(className);
Constructor constructor=clazz.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
Person person=(Person)constructor.newInstance("mmm",1);
System.out.println(person);
}