什么是反射
是被视为动态语言的关键,反射机制允许程序在执行期借助反射API用于获取任何类的内部信息,并且能够直接操作任意对象的内部属性和方法
加载完类之后,会在堆内存中生成Class类型的对象,一个类只生成一个(也就意味着通过反射创建的对象的地址值指向同一个),这个Class类型的对象包含了类的完整的结构信息
获取Class类的实例
方式1:类名.class(不常用,原因反射是动态性的,这样写就写死了)
Class clazz = Person.class;
方式2:调用getClass() 方法
Person p = new Person();
Class clazz = p.getClass();
方式3:通过Class类的静态方法forName(String path)获取
path : 类的全路径
Class clazz = Class.forName("包名.类名");
由于是你自己指定的,如果path找不到,就会抛ClassNotFoundException异常,这种方式能体现出反射的动态性
方式4:通过ClassLoader类加载器获取
ClassLoader clazz = 当前类.class.getClassLoader(); 当前类就是这两行代码写的类
Class clazz1 = clazz.loadClass("包名.类名")
也可能会抛ClassNotFoundException异常。
这几个方式都有使用的前提
- 方式1:需要知道具体的类
- 方式2:需要知道某个类的实例对象
- 方式3、方式4:需要知道一个类的全类名
哪些类型可以获取Class对象
class :外部类,内部类,静态内部类,局部内部类,匿名内部类,接口,注解,枚举类,基本数据类型,void
Class c1 = Object.class;
Class c2 = String[][].class;
Class c3 = int.class;
Class c4 = enum.class;
Class c5 = interface.class;
Class c6 = Class.class;
对于数组,只要数组元素类型和维度一样,就是指向同一个Class对象
类的加载器
ClassLoader
系统加载器-->扩展加载器-->引导类加载器
自定义类由系统加载器进行加载
引导类加载器负责加载java的核心类库
无法获取引导类加载器
类加载器的作用:将class字节码文件内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的Class对象,作为方法去中类数据的访问入口
通过反射常见运行时类对象
Class<Person> clazz = Person.class;
通过newInstance()抛异常:创建对应的运行时类对象,方法内部调用了运行时类的空参构造器
要求:运行时类必须提供空参构造器且权限得大,通常用public
Person p = clazz.newInstance();
获取运行时类的完整结构
返回运行时类实现的所有接口
Class <?>[] getInterfaces()
返回所继承的父类
Class<? Super T>getSuperclass()Constructors[] getConstructors():获取当前运行时类中所有的声明为public的构造器
Constructors[] getDeclaredConstructors() :获取当前运行时类中所有构造器
Method[] getDeclaredMethods():返回全部的方法
Method[] getMethods():返回所有修饰为public的方法
Field[] getDeclaredFields():返回所有属性
Field[] getFields():返回所有修饰为public的属性
int getModifiers():以整数的形式返回属性的修饰符
Class<?> getType():返回属性的类型
String getName():返回属性或方法名称
getReturnType():返回返回值类型
Class<?>[] getParameterTypes() :返回参数类型
Class[] getExceptionTypes():返回异常
获取注解
getAnnotation(注解类.class) 返回指定的注解
getDeclaredAnnotations() 返回所有注解
获取泛型
获取父类泛型:Type getGenericSuperclass()
获取泛型类型:Type[] getActualTypeArguments().getTypeName()
类所在的包
getPackage()
对于返回修饰符是int整数,可以通过
Modifiers.toString(int)来转换成代码的修饰符
获取运行时类的指定结构
Class clazz = Person.class
1.调用指定方法
clazz.getMethod(方法名,参数类型.class,...) 返回声明为public的方法
clazz.getDeclaredMethod(方法名,参数类型.class,..)
返回的Method对象.setAccessiable(true)来保证当前方法是可访问的
然后返回的Method.invoke(方法的调用者,实参),这个方法的返回值就是调用方法的返回值
调用静态方法时,方法的调用者可以为null,如果方法没有参数,可以不写
2.获取指定属性 抛异常
Field getField(属性名) 返回指定的public的属性,但因为属性通常被私有化了,因为这个方法不经常使用
Field getDeclaredField(属性名) 返回指定的属性
//通过返回的Field对象.setAccessiable(true)来保证当前属性是可访问的
Field对象.set(运行时类对象,要设置的属性值)
Field对象.get(运行时类对象)
3.调用指定构造器 抛异常,不常用,因为不通用
getDeclaredConstructor(参数列表.class...)
getConstructor(参数列表.class....)
返回的构造器对象.setAccessiable(true)来保证当前构造器是可访问的
然后通过构造器对象.newInstance(参数)来创建运行时类对象
本人是Java初学者,水平有限,本文章中如果有不对的地方,麻烦您能指出来。向您表示感谢。
584

被折叠的 条评论
为什么被折叠?



