文章目录
代码语言:txt复制- [1 简介](https://cloud.tencent.com/developer)
- [2 Class 类](https://cloud.tencent.com/developer)
- [2.1 获取Class类的实例](https://cloud.tencent.com/developer)
- [2.2 创建类对象](https://cloud.tencent.com/developer)
- [3 获取运行时类的完整结构](https://cloud.tencent.com/developer)
- [3.1 类的属性](https://cloud.tencent.com/developer)
- [3.2 类的方法](https://cloud.tencent.com/developer)
- [3.3 构造器](https://cloud.tencent.com/developer)
- [3.4 其他](https://cloud.tencent.com/developer)
- [4 调用类中的指定属性、方法和构造器](https://cloud.tencent.com/developer)
- [5 动态代理与AOP](https://cloud.tencent.com/developer)
1 简介
- Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
- Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
- 反射相关的主要API java.lang.Class:代表一个类 java.lang.reflect.Method:代表类的方法 java.lang.reflect.Field:代表类的成员变量 java.lang.reflect.Constructor:代表类的构造方法 …
2 Class 类
在Object类中定义了以下的方法,此方法将被所有子类继承:
- public final Class getClass()
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例。每一个运行时类只加载一次。通过Class可以完整地得到一个类中的完整结构。
2.1 获取Class类的实例
代码语言:javascript复制// 1.调用运行时类本身的.class属性
Class class1 = String.class;
System.out.println(class1.getName());
// 2.通过运行时类的对象获取
String string = new String();
Class class2 = string.getClass();
System.out.println(class2.getName());
// 3.通过Class的静态方法获取(通过此方式体会反射的动态性)
String className = "java.lang.String";
Class class3 = null;
try {
class3 = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(class3.getName());
// 4.通过类的加载器(了解)
ClassLoader classLoader = this.getClass().getClassLoader();
Class class4 = null;
try {
class4 = classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(class4.getName());
System.out.println(class1 == class2); // true
System.out.println(class2 == class3); // true
System.out.println(class3 == class4); // true
类加载器:
代码语言:javascript复制@Test
public void test4() throws ClassNotFoundException, IOException {
ClassLoader loader1 = ClassLoader.getSystemClassLoader();
ClassLoader loader2 = loader1.getParent();
ClassLoader loader3 = loader2.getParent();
System.out.println(loader1); // jdk.internal.loader.ClassLoaders$AppClassLoader@28c97a5
System.out.println(loader2); // jdk.internal.loader.ClassLoaders$PlatformClassLoader@24269709
System.out.println(loader3); // null
Class class1 = Person.class;
ClassLoader loader4 = class1.getClassLoader();
System.out.println(loader4); // jdk.internal.loader.ClassLoaders$AppClassLoader@28c97a5
// 测试某个类由哪个类加载器进行加载
String className = "java.lang.Object";
Class class2 = Class.forName(className);
ClassLoader loader5 = class2.getClassLoader();
System.out.println(loader5); // null
// 关于类加载器的一个主要方法
// 获取包下的配置文件
ClassLoader loader6 = this.getClass().getClassLoader();
InputStream is = loader6.getResourceAsStream("day20\jdbc.properties"); // 获取类路径下的指定文件的输入流
// 获取工程目录下的配置文件
// FileInputStream is = new FileInputStream(new File("jdbc.properties"));
Properties pros = new Properties();
pros.load(is);
String name = pros.getProperty("user");
System.out.println(name); // runner
System.out.println(pros.getProperty("password")); // 123456
}
2.2 创建类对象
代码语言:javascript复制String className = "day20.Person";
Class class1 = Class.forName(className);
代码语言:javascript复制// 方法一:
Object obj = class1.newInstance(); // 已弃用
Person person = (Person) obj;
代码语言:javascript复制// 方法二:
Constructor constructor = class1.getConstructor(String.class);
Person person2 = (Person) constructor.newInstance("hello");
3 获取运行时类的完整结构
3.1 类的属性
代码语言:javascript复制Class class1 = Person.class;
// 1.getFields(): 只能获取到运行时类中及其父类中声明为public的属性
Field[] fields = class1.getFields();
for (int i = 0; i < fields.length; i ) {
System.out.println(fields[i]);
}
// 2.getDeclaredFields(): 获取运行时类本身声明的所有的属性
Field[] fields1 = class1.getDeclaredFields();
for(Field field : fields1) {
// System.out.println(field);
// 1.获取每个属性的权限修饰符
int i = field.getModifiers();
System.out.print(Modifier.toString(i) " ");
// 2.获取属性的类型
Class type = field.getType();
System.out.print(type.getName() " ");
// 3.获取属性名
System.out.println(field.getName());
}
3.2 类的方法
代码语言:javascript复制// 1.getMethods():获取运行时类及其父类中所有的声明为public的方法
Method[] methods = class1.getMethods();
// 2.getDeclaredMethods():获取运行时类本身声明的所有的方法
Method[] methods2 = class1.getDeclaredMethods();
// 获取注解 权限修饰符 返回值类型 方法名 形参列表 异常
for(Method method : methods2) {
// 1.注解
Annotation[] anns = method.getAnnotations();
for(Annotation ann : anns) {
System.out.println(ann);
}
// 2.权限修饰符
System.out.print(Modifier.toString(method.getModifiers()) " ");
// 3.返回值类型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() " ");
// 4.方法名
System.out.print(method.getName());
// 5.形参列表
System.out.print("(");
Class[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i ) {
System.out.print(params[i].getName() " args-" i " ");
}
System.out.print(")");
// 6.异常类型
Class[] exps = method.getExceptionTypes();
if (exps.length != 0) {
System.out.print(" throws ");
}
for (int i = 0; i < exps.length; i ) {
System.out.print(exps[i].getName() " ");
}
System.out.println();
}
3.3 构造器
代码语言:javascript复制Constructor[] cons = class1.getConstructors();
Constructor[] cons1 = class1.getDeclaredConstructors();
3.4 其他
代码语言:javascript复制// 1.获取运行时类的父类
Class superClass = clazz.getSuperclass();
// 2.获取带泛型的父类
Type type = class1.getGenericSuperclass();
// 获取父类的泛型
ParameterizedType param = (ParameterizedType) type;
Type[] ars = param.getActualTypeArguments();
// 3.获取实现的接口
Class[] interfaces = class1.getInterfaces();
// 4.获取所在的包
Package package1 = class1.getPackage();
// 5.获取注解
Annotation[] anns = class1.getAnnotations();
// 6.获取内部类
Class[] classes = class1.getDeclaredClasses();
4 调用类中的指定属性、方法和构造器
- 属性
Class class1 = Person.class;
//1.获取指定的属性
//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
Field name = class1.getField("name");
//2.创建运行时类的对象
Person person = (Person) class1.newInstance();
//3.将运行时类的指定的属性赋值
name.set(person, "hello");
name.get(person); // 获取该属性值
// getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性
Field age = class1.getDeclaredField("age");
age.setAccessible(true); // 由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。
age.set(person, 20);
- 方法
Class class1 = Person.class;
//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
Method method = class1.getMethod("show");
Person person = new Person();
// 调用指定的方法:Object invoke(Object obj,Object ... obj)
Object returnVal = method.invoke(person);
Method method2 = class1.getMethod("toString");
Object returnVal1 = method2.invoke(person);
// 对于运行时类中静态方法的调用
Method method3 = class1.getMethod("Info");
method3.invoke(Person.class);
method3.invoke(null);
// getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
Method method4 = class1.getDeclaredMethod("display", String.class, Integer.class);
method4.setAccessible(true);
Object returnVal2 = method4.invoke(person, "hhhh", 3);
- 构造器
Class class1 = Person.class;
Constructor constructor = class1.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
Person person = (Person) constructor.newInstance("xixi", 20);
5 动态代理与AOP
Java学习笔记——设计模式:动态代理
注:以上笔记参考自尚硅谷