前言
JAVA反射机制是在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性, 方法, 注解, 继承实现的信息,也就你想要的这里都有. 对于任意一个对象, 都能够调用它的任意方法和属性, 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制.
反射是学习框架源码之前必须掌握的知识!
本篇主要是介绍api的使用
在线文档.
反射相关类简介
类 | 描述 |
---|---|
Class | 类信息 |
Field | 类的属性 |
Method | 类的方法 |
Constructor | 类的构造器 |
准备
先建要用到的类
一个父类
public abstract class AbstractClassDemo {
abstract public void absMethod();
}
一个接口
public interface InterfaceDemo {
void interfaceMethod();
}
一个类
public class ClassDemo extends AbstractClassDemo implements InterfaceDemo {
private static String staticField ;
private final String FINAL_FIELD = "final_field";
private static final String STATIC_FINAL_FIELD = "static_final_field";
private int id;
private String privateString;
protected Integer protectedInteger;
public String publicString;
public ClassDemo(){
}
public String thisPublicMethod(String str) throws ClassCastException,Exception{
System.out.println("thisPublicMethod " +str);
return str;
}
private static void staticPrivateMethod(String str,String str2){
System.out.println("staticPrivateMethod " + str +" " +str2);
}
@Override
public void absMethod() {
System.out.println("absMethod");
}
@Override
public void interfaceMethod() {
System.out.println("interfaceMethod");
}
public void testGetDeclaredClasses(){
new ClassDemo2().instance().pr();
}
public class ClassDemo2{
public void pr(){
}
public ClassDemo2 instance() {
//匿名内部类
return new ClassDemo2() {
@Override
public void pr(){
System.out.println("getDeclaredClasses: " + this.getClass().getDeclaringClass());
System.out.println("getEnclosingClass " + this.getClass().getEnclosingClass());
}
};
}
}
private class ClassDemo3{
}
private static class ClassDemo4{
}
public interface InterFace2{
}
}
Class
@Test
void testClass() throws Exception{
//三种获取类对象的方法
//通过Class.forName
Class clazz = Class.forName("com.xc.java.reflect.ClassDemo");
System.out.println("通过Class.forName: " + clazz);
//通过 类.class
Class clazz1 = ClassDemo.class;
System.out.println("通过 类.class: " + clazz1);
//通过对象getClass
Class clazz2 = new ClassDemo().getClass();
System.out.println("通过对象getClass: " + clazz2);
//获取类加载器
ClassLoader classLoader = clazz.getClassLoader();
System.out.println("类加载器classLoader: " +classLoader);
//获取内部所有public类,接口
Class[] classes = clazz.getClasses();
System.out.println("公共的内部类,接口 getClasses: " + classes);
//获取内部所有类,接口
Class[] declaredClasses = clazz.getDeclaredClasses();
System.out.println("所有的内部类,接口 declaredClasses: " + classes);
//获取该类实现的接口
Class[] interfaces = clazz.getInterfaces();
System.out.println("所有实现的接口getInterfaces: " + classes);
//获取类的限定类名
String name = clazz.getName();
System.out.println("限定类名 getName: " + name);
//获取类的非限定类名
String simpleName = clazz.getSimpleName();
System.out.println("非限定类名 getSimpleName: " + simpleName);
//获取类所在的包
Package aPackage = clazz.getPackage();
System.out.println("获取包 getPackage: " + aPackage);
//获取直接父类
Class superclass = clazz.getSuperclass();
System.out.println("获取父类对象 getSuperclass: " + superclass);
//父类(或解耦)转换子类
Class subClazz = clazz.asSubclass(AbstractClassDemo.class);
System.out.println("父类转子类 subClazz" +subClazz);
//创建一个对象
ClassDemo classDemo = (ClassDemo)clazz.newInstance();
System.out.println("新建一个对象:newInstance " + classDemo);
//getEnclosingClass(支撑匿名内部类) 和 getDeclaringClass(不支持匿名内部类) 都是内部类获取外部类.
classDemo.testGetDeclaredClasses();
}
输出结果
通过Class.forName: class com.xc.java.reflect.ClassDemo
通过 类.class: class com.xc.java.reflect.ClassDemo
通过对象getClass: class com.xc.java.reflect.ClassDemo
类加载器classLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
公共的内部类,接口 getClasses: [Ljava.lang.Class;@479d31f3
所有的内部类,接口 declaredClasses: [Ljava.lang.Class;@479d31f3
所有实现的接口getInterfaces: [Ljava.lang.Class;@479d31f3
限定类名 getName: com.xc.java.reflect.ClassDemo
非限定类名 getSimpleName: ClassDemo
获取包 getPackage: package com.xc.java.reflect
获取父类对象 getSuperclass: class com.xc.java.reflect.AbstractClassDemo
父类转子类 subClazzclass com.xc.java.reflect.ClassDemo
新建一个对象:newInstance com.xc.java.reflect.ClassDemo@40ef3420
getDeclaredClasses: null
getEnclosingClass class com.xc.java.reflect.ClassDemo$ClassDemo2
Field
@Test
void testField() throws Exception {
Class clazz = ClassDemo.class;
Object obj = clazz.newInstance();
//获取单个属性 public
clazz.getField("publicString");
//获取单个属性 private
clazz.getDeclaredField("publicString");
//获取类的所有public属性
Field[] fields = clazz.getFields();
System.out.println("获取所有public 属性: ");
for(Field field : fields){
System.out.println(field.getModifiers() + " " + field.getType().getSimpleName() + " " +field.getName() + " " +field.get(obj));
}
//获取所有属性
Field[] declaredFields = clazz.getDeclaredFields();
System.out.println("获取所有属性: ");
for(Field field : declaredFields){
//设置可访问
field.setAccessible(true);
if("publicString".equals(field.getName())){
//修改公共属性
field.set(obj,"修改公共属性success");
}else if("privateString".equals(field.getName())){
//修改私有属性
field.set(obj,"修改私有属性success");
}else if("FINAL_FIELD".equals(field.getName())){
//修改私有非静态常量
//modifiers使修饰符的值
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers()&~Modifier.FINAL);
field.set(obj,"修改私有非静态常量success");
}else if("STATIC_FINAL_FIELD".equals(field.getName())){
//修改私有静态常量
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers()&~Modifier.FINAL);
field.set(obj,"修改私有静态常量success");
}
System.out.println(field.getModifiers() + " "
+ field.getType().getSimpleName() + " "
+ field.getName() + " "
+ field.get(obj));
}
}
/**
* JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。
* 对应表如下:
* PUBLIC: 1
* PRIVATE: 2
* PROTECTED: 4
* STATIC: 8
* FINAL: 16
* SYNCHRONIZED: 32
* VOLATILE: 64
* TRANSIENT: 128
* NATIVE: 256
* INTERFACE: 512
* ABSTRACT: 1024
* STRICT: 2048
*/
获取所有public 属性:
1 String publicString null
获取所有属性:
10 String staticField null
2 String FINAL_FIELD 修改私有非静态常量success
10 String STATIC_FINAL_FIELD 修改私有静态常量success
2 int id 0
2 String privateString 修改私有属性success
4 Integer protectedInteger null
1 String publicString 修改公共属性success
Method
@Test
void testMethod() throws Exception{
Class clazz = ClassDemo.class;
ClassDemo classDemo = (ClassDemo) (clazz.newInstance());
//获取所有共有方法
Method[] methods = clazz.getMethods();
//获取方法: 通过方法名称 和 ...所有参数类型
Method thisPublicMethod = clazz.getMethod("thisPublicMethod", String.class);
//获取方法所有throws异常
Class[] exceptionTypes = thisPublicMethod.getExceptionTypes();
//方法所在类
Class<?> declaringClass = thisPublicMethod.getDeclaringClass();
//方法参数个数
int parameterCount = thisPublicMethod.getParameterCount();
//返回方法所有参数类型
Class<?>[] parameterTypes = thisPublicMethod.getParameterTypes();
//返回结果类型
Class<?> returnType = thisPublicMethod.getReturnType();
//返回所有Parameter
Parameter[] parameters = thisPublicMethod.getParameters();
//获取所有方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
//设置访问权限
declaredMethod.setAccessible(true);
//执行方法
declaredMethod.invoke(classDemo ,new Object[declaredMethod.getParameterCount()]);
}
}
Constructor
@Test
public void testConstructor() throws Exception{
Class clazz = ClassDemo.class;
//获取所有共有构造器
Constructor[] constructors = clazz.getConstructors();
System.out.println("获取所有共有构造器 " + constructors);
//获取所有构造器
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
System.out.println("获取所有构造器 " + declaredConstructors);
//根据参数类型和个数获取构造器 public
Constructor constructor = clazz.getConstructor();
System.out.println("根据参数类型和个数获取public的构造器 " + constructor);
//根据参数类型和个数获取构造器
Constructor declaredConstructor = clazz.getDeclaredConstructor();
System.out.println("根据参数类型和个数获取构造器 " + declaredConstructor);
//通过构造器创建一个对象
Object object = declaredConstructor.newInstance();
System.out.println("通过构造器创建一个对象 " + object);
}
输出
获取所有共有构造器 [Ljava.lang.reflect.Constructor;@333291e3
获取所有构造器 [Ljava.lang.reflect.Constructor;@479d31f3
根据参数类型和个数获取public的构造器 public com.xc.java.reflect.ClassDemo()
根据参数类型和个数获取构造器 public com.xc.java.reflect.ClassDemo()
通过构造器创建一个对象 com.xc.java.reflect.ClassDemo@40ef3420
总结
你想要的,反射这里都有.