反射机制
反射机制用于动态创建对象并动态调用方法的机制。
一、Class类
- java.lang.Class类的实例用于描述java应用程序中的类和接口,可以表示一种数据类型
- 该类没有构造方法,该类的实例有java虚拟机和类加载器自动构造完成,是加载到内存中的运行时类,只要有一个类加载到java虚拟机内存中,就会有对应的信息(运行时类)即Class对象
- 获取Class对象的方式
- 使用数据类型.Class的方式获取对应类型的Class对象,数据类型包括基本数据类型和引用数据类型,所以类,接口,数组都可以(Integer.class ---- class java.lang.Ineger)
- 使用引用/对象.getClass()的方式获取对应类型的Class对象,类/接口的实例.getClass()
- 使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象,返回的是基本数据类型(Integer.TYPE ---- int)
- 使用Class.forName()的方式获取指定参数类型的Class对象, 必须写完类名 (Class.forName(java.lang.String)正确,而Class.forName(String)找不到类信息 ),且不能获取基本数据类型
- 使用类加载器ClassLoader的方式获取指定类型的Class对象
import java.util.List;
public class ClassTest {
public static void main(String[] args) {
//获取Class对象的方式
//1. 使用数据类型.class的方式可以获取对应类型的Class对象
Class<Integer> integerClass = int.class;
System.out.println(integerClass); //int
Class<String> stringClass = String.class;
System.out.println(stringClass); // class java.lang.String
Class<Integer> integer = Integer.class;
System.out.println(integer); //class java.lang.Integer
Class<ClassTest> classTestClass = ClassTest.class;
System.out.println(classTestClass);// class ClassTest
Class<List> listClass = List.class;
System.out.println(listClass); //interface java.util.List
System.out.println("------------------------");
//2.使用引用/对象.getClass()的方式可以获取对应类型的Class对象
String str="hello";
System.out.println(str.getClass());//class java.lang.String
Integer num=1;
System.out.println(num.getClass());//class java.lang.Integer
int[] arr=new int[3];
System.out.println(arr.getClass());//class [I
int n=1;
// System.out.println(n.getClass()); 没有getClass()方法,不是引用数据类型
System.out.println("------------------------");
//3.使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象
// System.out.println(String.TYPE); String不是包装类,无法反射
System.out.println(Integer.TYPE); //返回的是基本数据类型 int
System.out.println(Boolean.TYPE);//boolean
System.out.println("------------------------");
//4.使用Class.forName()的方式来获取参数指定类型的Class对象
Class<?> string = null;
try {
//string = Class.forName("String"); //ClassNotFoundException: String,必须是完整类名,格式: 包名.类名
string=Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(string); //class java.lang.String
System.out.println("------------------------");
//5.使用类加载器ClassLoader的方式获取指定类型的Class对象,使用方式必须是已加载的类.class.getClassLoader()
ClassLoader classLoader = String.class.getClassLoader();//null,说明String类还未加载到内存中
classLoader=ClassTest.class.getClassLoader();//jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc说明已加载
System.out.println(classLoader);
Class<?> aClass=null;
try {
aClass=classLoader.loadClass("java.lang.String");//通过loadClass可以获取指定类型的Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(aClass);//class java.lang.String
}
}
- 反射机制创建对象
- 适用于读取配置文件通过反射创建对象
方法声明 功能介绍 static Class<?> forName(String className) 用于获取参数指定类型对应的Class对象并返回 T newInstance() 用于创建该Class对象所表示类的新实例 - 通过Constructor 类创建对象,java.lang.reflect.Constructor类用于描述获取到的构造方法信息
- 适用于读取配置文件通过反射创建对象
| 方法声明 | 功能介绍 |
| Constructor getConstructor(Class<?>... parameterTypes) |
用于获取此Class对象所表示类型中参数指定的 公共构造方法 |
| Constructor<?>[] getConstructors() | 用于获取此Class对象所表示类型中所有的公共 构造方法 |
| 方法声明 | 功能介绍 |
| T newInstance(Object... initargs) |
使用此Constructor对象描述的构造方法来构造Class对象代表类 型的新实例 |
| int getModifiers() | 获取方法的访问修饰符 |
| String getName() | 获取方法的名称 |
import com.rf.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
public class PersonConstructerTest {
public static void main(String[] args) throws Exception {
//1.使用原有方式创建无参person对象
Person person = new Person();
System.out.println(person);//Person{name='null', age=0}
//2. 反射机制1 T newInstance()创建无参person对象
Class<?> aClass = Class.forName("com.rf.Person");
System.out.println(aClass.newInstance());//Person{name='null', age=0}, 方法已过时
//3. 反射机制2 Constructor类创建无参person对象
Constructor<?> constructor = aClass.getConstructor();
System.out.println(constructor.newInstance());//Person{name='null', age=0},
//4. 原始方式创建有参person对象
person = new Person("张飞", 12);//Person{name='张飞', age=12}
System.out.println(person);
//5. 反射机制Constructor类创建有参person对象
//获取Class对象对应的有参构造方法,传递参数传入形参Class对象
constructor = aClass.getConstructor(String.class, int.class);
System.out.println(constructor.newInstance("张飞", 12));//Person{name='张飞', age=12}
//6.不知道类对象的中的构造方法形参类型,通过constructors获取所有公共构造方法
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor constructor1:constructors) {
System.out.println("构造器名称"+constructor1.getName());
System.out.println("访问修饰符"+constructor1.getModifiers());
// System.out.println("方法参数类型"+ Arrays.toString(constructor1.getParameterTypes())); //constructor1没有重写toString方法,所以不能直接打印
Class[] types = constructor1.getParameterTypes();
for (Class c:types) {
System.out.print(c+" ");//class java.lang.String int 构造器名称com.rf.Person
}
System.out.println();
}
//后续在反射创建
}
}
- Filed类获取单个成员变量信息 java.lang.reflect.Field类
| 方法声明 | 功能介绍 |
| Field getDeclaredField(String name) |
用于获取此Class对象所表示类中参数指定的单个成员变量 信息 |
| Field[] getDeclaredFields() | 用于获取此Class对象所表示类中所有成员变量信息 |
-
- filed常用方法
| 方法声明 | 功能介绍 |
| Object get(Object obj) | 获取参数对象obj中此Field对象所表示成员变量的数值 |
| void set(Object obj, Object value) |
将参数对象obj中此Field对象表示成员变量的数值修改为参数 value的数值 |
| void setAccessible(boolean flag) |
当实参传递true时,则反射对象在使用时应该取消 Java 语言访 问检查 |
| int getModifiers() | 获取成员变量的访问修饰符 |
| Class<?> getType() | 获取成员变量的数据类型 |
| String getName() | 获取成员变量的名称 |
- Method类:java.lang.reflect.Method类主要用于描述获取到的单个成员方法信息
| 方法声明 | 功能介绍 |
| Method getMethod(String name, Class<?>... parameterTypes) |
用于获取该Class对象表示类中名字为name参数为 parameterTypes的指定公共成员方法 |
| Method[] getMethods() | 用于获取该Class对象表示类中所有公共成员方法 |
-
- method常用方法
| 方法声明 | 功能介绍 |
| Object invoke(Object obj, Object... args) |
使用对象obj来调用此Method对象所表示的成员方法,实 参传递args |
| int getModifiers() | 获取方法的访问修饰符 |
| Class<?> getReturnType() | 获取方法的返回值类型 |
| String getName() | 获取方法的名称 |
| Class<?>[] getParameterTypes() | 获取方法所有参数的类型 |
| Class<?>[] getExceptionTypes() | 获取方法的异常信息 |
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class FieldTest {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.rf.Person");
Constructor<?> constructor = aClass.getConstructor(String.class, int.class);
Object o = constructor.newInstance("zhangfei", 20);
//field获取单个成员变量的信息
//1.通过Class对象获取该对象的成员变量,
Field field = aClass.getDeclaredField("name");//成员变量名称,该成员变量的访问权限是private
//获取任意访问权限的成员变量时必须设置成员变量的获取属性为true,否则java.lang.IllegalAccessException
field.setAccessible(true);//证明反射机制可以获取任意访问权限的成员变量和方法
//2.获取对应成员变量的变量值,传入的object是实例化类的对象
System.out.println(field.get(o));//张飞
//3.修改成员变量属性
field.set(o,"guanyu");
System.out.println(field.get(o));//guanyu
//4.获取多个成员变量
Field[] fields = aClass.getDeclaredFields();
for (Field f:fields) {
System.out.println("成员变量名称为"+f.getName());
System.out.println("成员变量属性为"+f.getModifiers()); //1 表示public 2 表示private 3 表示package 4 表示protected
System.out.println("成员变量参数为"+f.getType());
}
System.out.println("----------------------");
//method获取单个成员方法的信息
//1.通过Class对象获取该对象的成员方法,传入参数1. 方法名,2形参类型
Method getName = aClass.getMethod("getName");
System.out.println(getName.invoke(o));//返回姓名,guanyu
//2.调用对应成员方法获取返回值,传入参数有1,object是实例化类的对象 2,形参
Method setAge = aClass.getMethod("setAge", int.class);
setAge.invoke(o,25);
Field fage=aClass.getDeclaredField("age");
fage.setAccessible(true);
System.out.println(fage.get(o));//25
//4.获取多个成员方法及属性
Method[] methods = aClass.getMethods(); //把继承实现的所有方法和子类独有方法都打印
for (Method method:methods) {
System.out.println("方法名为"+method.getName());
System.out.println("方法权限"+method.getModifiers());
System.out.println("方法返回值类型"+method.getReturnType());
System.out.println("方法传递形参为");
Class<?>[] parameterTypes = method.getParameterTypes();
for ( Class<?> p:parameterTypes) {
System.out.print(p+" ");
}
System.out.println("方法可能抛出的异常类型为");
Class<?>[] exceptionTypes = method.getExceptionTypes();
for ( Class<?> e:exceptionTypes) {
System.out.print(e+" ");
}
}
}
}
- 通过类对象获取结构信息,Class.forName("com.rf.Person");的Class对象
| 方法声明 | 功能介绍 |
| Package getPackage() | 获取所在的包信息 |
| Class<? super T> getSuperclass() | 获取继承的父类信息 |
| Class<?>[] getInterfaces() | 获取实现的所有接口 |
| Annotation[] getAnnotations() | 获取注解信息 |
| Type[] getGenericInterfaces() | 获取泛型信息 |
import java.lang.reflect.Constructor;
public class ConstructTest {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.rf.Person");
Constructor<?> constructor = aClass.getConstructor(String.class, int.class);
Object o = constructor.newInstance("guanyu", 29);
//Package getPackage() 获取所在的包信息
System.out.println("所在的包信息"+aClass.getPackage());
System.out.println("所在的包名"+aClass.getPackageName());
//Class<? super T> getSuperclass() 获取继承的父类信息
System.out.println("继承的父类信息"+aClass.getSuperclass());
System.out.println("继承的指定的泛型父类"+aClass.getGenericSuperclass());
//Class<?>[] getInterfaces() 获取实现的所有接口
System.out.println("实现的所有接口"+aClass.getInterfaces()); //所有接口,未指定泛型
//Annotation[] getAnnotations() 获取注解信息
System.out.println("注解信息"+aClass.getAnnotations());
//Type[] getGenericInterfaces() 获取泛型信息
System.out.println("实现的指定的泛型接口"+aClass.getGenericInterfaces());
}
}
浙公网安备 33010602011771号