Java反射机制可以让我们在编译期之外的运行期检查类,接口,变量以及方法的信息.
反射还可以让我们在运行实例对象,调用方法,通过调用get/set方法获取变量的值.
反射机制中可以在程序中访问已经加载到JVM中java对象的描述,实现访问,
检测和修改描述java对象本身的信息的功能
使用java反射机制可以在运行时期检查java类的信息,
通过获取类的信息你可以获取以下相关的内容:Class对象,类名,
修饰符,包信息,父类,实现接口,构造器,方法,变量,注解等等.
1.Class对象
获取类的字节码对象有三种方式:
类名.class
Class.forName(包名+类名)
实例对象.getClass();
实例如下:
package myproject2;
* 测试反射的方法
* @author renjiaxing
public class TestReflectMethod {
public static void main(String[] args) {
//Class> aClass=class1.class;
//Class>aClass= new class1().getClass();
try {
Class<?>aClass = Class.forName("myproject2.class1");
2.类名
可以使用获取的字节码对象获取类名(这里有两种形式)
一种是获取类的全限定名名称(包名+类名):getName()
另一种是获取类的名称(不包含包名):getSimpleName()
实例如下:
Class<?>aClass = Class.forName("myproject2.class1");
String className = aClass.getName();
String simpleName = aClass.getSimpleName();
System.out.println(className);
System.out.println(simpleName);
3.修饰符
可以通过字节对象来访问一个类的修饰符,即public,private,static等等的关键字
你可以使用如下方法 getModifiers()如图:
这里注意:getModifiers()返回的是一个int类型,还需要使用import java.lang.reflect.Modifier;中的方法验证是哪个修饰符.
int modifiers = aClass.getModifiers();
Modifier modifier = new Modifier();
boolean pubtype = modifier.isPublic(modifiers);
System.out.println(pubtype);
4.包信息
使用字节码对象通过以下方法来获取包信息:getPackage()
代码如下:
Class<?>aClass = Class.forName("myproject2.class1");
Package packageName = aClass.getPackage();
System.out.println(packageName);
5.父类
通过字节码对象获取类的父类对象(如果业务需要还可以在父类基础上继续反射)
Class<?>aClass = Class.forName("myproject2.class1");
Class<?> supClass = aClass.getSuperclass();
System.out.println(supClass);
6.实现的接口
通过字节码对象获取实现的接口.由于一个类可以实现很多的接口,因此getInterfaces()返回的是一个Class>数组,注意:仅仅是只返回了当前类实现的接口,父类的实现的接口不会返回.尽管实际上当前类已经实现了父类的接口.
Class<?>aClass = Class.forName("myproject2.class1");
Class<?>[] interfaces = aClass.getInterfaces();
System.out.println(interfaces);
7.构造方法
通过字节码对象获取每一个公开的(public)的构造方法,以及获取指定参数的构造方法,获取构造方法的参数,利用构造方法实例化一个类,代码如下:
try {
Class<?>aClass = Class.forName("myproject2.class1");
Constructor<?>[] constructors = aClass .getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
Constructor<?> constructor= aClass.getConstructor(new Class[]{int.class});
System.out.println(constructor);
Parameter[] parameters = constructor.getParameters();
Class<?>[] parameterTypes = constructor.getParameterTypes();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
for (Class<?> class1 : parameterTypes) {
System.out.println(class1);
}
Object newInstance = constructor.newInstance(123);
System.out.println(newInstance);
8.变量
使用反射机制,可以在运行期检查一个类的成员变量获取或者设置变量的值.注意这里变量修饰符的权限问题;
Class<?>aClass = Class.forName("myproject2.class1");
Field[] fields = aClass .getFields();//获取修饰符为public的
Field field = aClass.getField("a");
System.out.println(field.getName());
System.out.println(field .getType());
class1 myClass1 = (class1) aClass.newInstance();
Object fieldObject = field.get(myClass1);
field.set(myClass1, fieldObject);
Field field = aClass.getDeclaredField("b");获取private的成员变量
field.setAccessible(true);这行代码关闭访问检查
class1 myClass1 = (class1) aClass.newInstance();
//用字节码获取一个实例对象
String fieldObject =(String) field.get(myClass1);
field .set(myClass1, fieldObject);
9.方法
方法与变量同样的要考虑修饰符的问题
Class<?>aClass = Class.forName("myproject2.class1");
Method[] methods = aClass.getMethods();
Method method = aClass.getMethod("a", new Class[]{String.class});
System.out.println(method);
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> class1 : parameterTypes) {
System.out.println(class1);
}
Class<?> returnType = method.getReturnType();
System.out.println(returnType);
class1 myClass1=(class1) aClass.newInstance();
method.invoke(myClass1, "String[]");//如果是静态方法的话就用null
Method declaredMethod = aClass.getDeclaredMethod("b", new Class[]{String.class});
System.out.println(declaredMethod);
declaredMethod.setAccessible(true);
class1 class2= (class1) aClass.newInstance();
method.invoke(null, "String[]");
10.注解
通过字节码反射获取类上的注解,方法上的注解,属性上的注解,以及参数的注解
Class<?>aClass = Class.forName("myproject2.class1");
获取类上的注解
Annotation[] annotations = aClass.getAnnotations();
Myanno annotation = aClass.getAnnotation(Myanno.class);
获取方法上的注解
Method method = aClass.getMethod("a", new Class[]{String.class});
Annotation[] annotations2 = method.getAnnotations();
Myanno annotation2 = method.getAnnotation(Myanno.class);
System.out.println(annotation2);
获取方法参数的注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class<?>[] parameterTypes = method.getParameterTypes();
int i=0;
for (Annotation[] annotations3 : parameterAnnotations) {
Class<?> parameter = parameterTypes[i++];
for (Annotation annotation4 : annotations3) {
if (annotation4 instanceof Myanno) {
Myanno myanno=(Myanno) annotation4;
System.out.println(parameter.getName());
System.out.println(myanno.name());
System.out.println(myanno.value());
}
}
}
获取成员变量属性的注解
Field field = aClass.getField("a");
Annotation[] declaredAnnotations = field.getDeclaredAnnotations();
Myanno declaredAnnotation = field.getDeclaredAnnotation(Myanno.class);
11.反射还可以使用在泛型擦除,数组的处理(使用java.lang.reflect.Array来处理),动态代理…后期会续