1 反射机制
一般情况下编写的代码都是固定的,也就是说无论运行多少次执行的结果都是相同的,但是在某些特殊情况下编写代码时不确定要创建什么类型的对象,也不确定要调用什么方法,这时候希望可以通过运行时传递的参数来决定,该机制叫做动态编程技术,也叫做反射机制。
反射机制简单来说就是动态创建对象并且动态调用方法的机制,在实际开发中有很多框架就是基于java反射机制实现的。
2 Class类
Class类可以描述Java应用程序中的类和接口,也就是一种数据类型,且Class类是没有构造方法的,该类的实例是由Java 虚拟机和类加载器自动构造完成的,本质上就是加载到内存中的运行时类。
获取Class对象的五种方式:
- 使用数据类型.class的方式获取对应类型的Class对象
- 使用引用/对象.getClass()的方式获取对应类型的Class对象
- 使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象
- 使用Class.forName()的方式可以获取参数指定类型的Class对象
- 使用类加载器ClassLoader的方式获取指定类型的Class对象
Class类的常用方法:
| 方法声明 | 功能介绍 |
|---|---|
| static class<?> forName(String className) | 获取参数指定类型对应的Class对象并返回 |
| T newInstance() | 创建该Class对象所表示的新实例 |
| Constructor getConstructor(Class<?>... parameterTypes) | 获取此Class对象所表示类型中参数指定的公共构造方法 |
| Constructor<?>[] getConstructors() | 获区此Class对象所表示类型中的所有公共构造方法 |
| Filed getDeclaredFiled(String name) | 获取此Class对象所表示类中参数指定的单个成员变量信息 |
| Filed[] getDeclaredFileds() | 获取Class对象所表示类中所有成员变量信息 |
获取Class对象的具体代码:
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException {
Class c1=String.class;
System.out.println("c1= "+c1);
String str=new String("hello");
c1=str.getClass();
System.out.println("c1= "+c1);
c1=Integer.TYPE;
System.out.println("c1= "+c1);
c1=Class.forName("java.lang.String");
System.out.println("c1= "+c1);
ClassLoader cl=ClassTest.class.getClassLoader();
c1=cl.loadClass("java.lang.String");
System.out.println("c1= "+c1);
}
}
3 Constructor类和Field类
Constructor类主要描述获取到的构造方法信息,其常用的方法有:
| 方法声明 | 功能介绍 |
|---|---|
| T newInstance(Object... init) | 使用此Constructor对象描述的构造方法来构造Class对象代表类型的新实例 |
| int getModifiers() | 获取方法的访问修饰符 |
| String getName() | 获取方法的名称 |
| Class<?>[] getParameterTypes() | 获取方法的所有参数类型 |
Field类主要描述获取到的单个成员变量信息,其常用方法有:
| 常用方法 | 功能介绍 |
|---|---|
| Object get(Object ob) | 获取参数对象ob中此Field对象所表示成员变量的数值 |
| void set(Object ob,Object value) | 将参数对象ob中此Field对象所表示成员变量的数值修改为参数value的数值 |
| void setAccessible(boolean flag) | 当参数传递true时,则反射对象在使用时取消Java语言访问检查 |
| int getModifiers() | 获取成员变量的访问修饰符 |
| Class<?> getType() | 获取成员变量的数据类型 |
| String getName() | 获取成员变量的名称 |
Constructor类和Field类使用实例:
import java.lang.reflect.Constructor;
public class ConstructorTest {
public static void main(String[] args) throws Exception {
Class c=Class.forName("Person");
Constructor constructor=c.getConstructor();
System.out.println("使用无参方式构造对象是:"+constructor.newInstance());
Constructor c1=c.getConstructor(int.class,String.class);
System.out.println("使用有参方式构造对象是:"+c1.newInstance(22,"zhangfei"));
Constructor[] c2=c.getConstructors();
for(Constructor t:c2){
System.out.println("构造方法访问修饰符"+t.getModifiers());
System.out.println("构造方法的名称"+t.getName());
System.out.println("所有构造方法的参数是:");
Class[] par=t.getParameterTypes();
for(Class cla:par){
System.out.println("cla= "+cla);
}
}
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FieldTest {
public static void main(String[] args) throws Exception {
Class c=Class.forName("Person");
Constructor constructor=c.getConstructor(int.class,String.class);
Object obj = constructor.newInstance(22, "zhangfei");
Field field = c.getDeclaredField("age");
field.setAccessible(true);
System.out.println("获取到的成员变量值是:"+field.get(obj));
field.set(obj,33);
System.out.println("修改后的成员变量值是:"+field.get(obj));
Field[] declaredFields = c.getDeclaredFields();
for(Field f:declaredFields){
System.out.println("成员变量名"+f.getName());
System.out.println("成员变量修饰符"+f.getModifiers());
System.out.println("成员变量类型"+f.getType());
}
}
}
4 Method类以及获取其他结构信息
Method类主要用于描述获取到的单个成员方法信息,其常用方法如下:
| 方法声明 | 功能介绍 |
|---|---|
| Object invoke(Object ob,Object... args) | 使用对象ob调用此Method对象所表示的方法,实参传递args |
| int getModifiers() | 获取方法的访问修饰符 |
| Class<?> getReturnType() | 获取方法的返回值类型 |
| String getName() | 获取方法的名称 |
| Class<?>[] getParameterTypes() | 获取方法所有参数的类型 |
| Class<?>[] getExceptionTypes() | 获取方法的异常信息 |
获取其他结构信息的方法有:
| 方法声明 | 功能介绍 |
|---|---|
| Package getPackage() | 获取所在包信息 |
| Class<? Super T> getSuperClass() | 获取继承的父类信息 |
| Class<?>[] getInterfaces() | 获取实现的所有接口 |
| Annotion[] getAnnotions() | 获取注解 |
| Type[] getGenericInterfaces() | 获取泛型信息 |
关于Mthod类以及获取其他结构信息的实例代码如下:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MethodTest {
public static void main(String[] args) throws Exception {
Class c=Class.forName("Person");
System.out.println("获取到的包信息"+c.getPackage());
System.out.println("获取到的父类信息"+c.getSuperclass());
Constructor constructor = c.getConstructor(int.class, String.class);
Object obj = constructor.newInstance(26, "guanyu");
Method method = c.getMethod("getName");
Object invoke = method.invoke(obj);
System.out.println("调用方法返回的结果是:"+invoke);
Method[] methods = c.getMethods();
for(Method m:methods){
System.out.println("方法的访问修饰符是:"+m.getModifiers());
System.out.println("方法的返回类型是:"+m.getReturnType());
System.out.println("方法的名称:"+m.getName());
System.out.println("获取到的参数类型是");
Class<?>[] parameterTypes = m.getParameterTypes();
for(Class cl:parameterTypes){
System.out.println("cl: "+cl);
}
System.out.println("---------------------------------");
System.out.println();
}
}
}