今天学习了java反射机制的相关知识,学习内容如下:
1.借助于ReflectionAPI实现在程序运行状态过程中,取得任何类的内部信息,在程序运行过程中可以构造任意一个类的对象,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法,这种动态获取程序信息,以及动态调用对象的功能称为java反射机制;
2.java反射机制的功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时查看任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
在运行时给任意一个对象的属性赋值;
生产动态代理;
3.Class类:
java在将.class文件载入时,JVM会产生一个Java.lang.Class对象表示该.class字节码文件。class是一个比较特殊的类,是java反射机制的基础。Class类的对象表示正在运行的java程序中的类或接口,Class没有公共构造方法,其对象是JVM在加载类时通过调用类加载器中的defineClass()方法创建的,因此不能显示创建一个Class类的对象。通过Class对象,才可以获取这个类对象的其他信息,每个类被加载后系统就会生成对应的Class类对象,一旦类被加载到JVM中,同一个类将不会被再次载入;
4.如何获得Class对象:
(1)通过类名.class获得;
(2)通过Class的静态方法forName获得;
(3)通过某个类对象的.getClass()方法获得;
(4)使用类装载器的loadClass()方法获得;
java
//使用class的静态方法forName获得
Class<?> c1 = Class.forName("demo.Student");
//使用类名调用class属性来获得
Class<?> c2 =Student.class;
//使用该类对象的getClass方法来获得类的对象
Student student = new Student("小明",12);
Class<?> c3 = student.getClass();
//使用类装载器
ClassLoader classLoader = Student.class.getClassLoader();
Class<?> c4 = classLoader.loadClass("demo.Student");
5.那些类型可以有Class对象:
class:外部类,成员内部类,静态内部类,局部内部类,匿名内部类;
interface:接口;
数组;
enum 枚举;
annotation:注解;
基本数据类型和void;
6.ClassLoader
java类装载器的作用就是在运行时加载类,基于三个机制:
委托机制:将加载一个类的请求交给父类加载器,如果这个父类加载器找不到要加载的类,那么子类再加载他,比如加载一个String类;
可见性机制:子类加载器可以看见所有父类加载器加载的类,但是父类加载器看不到子类加载器加载的类;
单一性机制:加载一个类,仅加载一次,在委托机制中父类已经加载的一个类子类不会再加载了;
加载的两种方式:
显示加载:通过Class.forName()等方法来显示的加载想要的类;
隐式加载:程序在运行过程中,通过new等方法创建对象时,隐式的调用加载器,将其所属类加载到JVM中;
类加载器的分类:
BootStrapClassLoader:根装载器,使用C++编写在Java中看不到他,用于装载核心类库;
ExtClassLoader(PlatformClassLoader):扩展类装载器,装载扩展目录ext中的jar;
AppClassLoader:应用类装载器,负责classpath类的装载;
JVM在装载类的时候使用全盘委托机制,即除了显示的使用一个ClassLoader,不然该类的依赖类以及该类的引用类都将被装载;
JVM在装载类时先将基础类进行装入,再在其他类使用的时候对其装入,这样可以节省内存开销;
7.Constuctor类:
获得Constructor类对象的方法:
java
//通过Class类的getDeclaredConstructor()方法获得private和public修饰的构造方法,获得private修饰的构造方法时需要使用setAccessible来设置可访问权限,但是使用getConstructor()方法获得的只能时public方法;
Constructor<?> constructor = Student.class.getDeclaredConstructor();
//通过getParameterTypes()方法获得参数列表数组;
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
//通过newInstance获得类实例对象
Object o = constructor.newInstance();
8.Field类:
通过getFields()可以获得类中的所有公有属性和继承自父类的属性;
通过getDeclaredFields()获得该类中的所有属性(含private),不包含继承自父类的属性;
通过getField(属性名)可以获得指定属性(不包含private);
通过getDeclaredField(属性名)可以获得指定属性(包含private,需setAccessible(true));
通过set可以给指定对象设置属性的值;
通过getModifiers方法获得访问修饰符;

9.Method类:
通过getMethods()可以获得类中的所有公有方法和继承自父类的方法;
通过getDeclaredMethods()获得该类中的所有方法(含private),不包含继承自父类的方法;
通过getMethod(方法名,参数类名)可以获得指定方法(不包含private);
通过getDeclaredMethod(属性名)可以获得指定方法(包含private,需setAccessible(true));
通过invoke(对象名,参数列表)可以执行方法,返回值为Object类型;
通过getModifiers方法获得访问修饰符;
10.反射获得泛型:
反射可以获得泛型的场景:
成员变量的泛型;
方法参数的泛型;
方法返回值的泛型;
获取带有泛型的超类或带有泛型的实现的接口;
不能获取局部变量的泛型;
通过调用Method/Field/Class的getGenericType/getGenericParameterTypes/getGenericReturnType...,以返回一个Type类型的对象或数组,可以通过instance方法判断该Type对象是否属于ParameterizedType,如果属于的话可以将其强转为ParameterizedType,再调用getActualTypeArguments()方法获得泛型中的参数的类型;