java反射

反射就是利用类名获得实例

Class.forName(className)获取到Class

Class中存在方法getDeclaredConstructor获取它的构造函数

构造函数有newInstance方法获取实例

Class.forName("java.lang.String").getDeclaredConstructor(String.class).newInstance("zhong")

java反射_第1张图片

Class类里不仅可以获得构造器,还可以获得属性和方法

其中Method很有意思,

原来调用方法是,"wang".equals("jian")。类在前,方法在后

现在可以用,

Method equals = Class.forName("java.lang.String").getMethod("equals");

equals.invoke("wang","jian")的形式

注意method里会存参数类型等信息,使用不同类调用时要注意函数的参数是够相同

介绍(动态性)

class位于java.lang.Class

其它的在java.lang.reflect里面Filed/Method/Constructor

Class实例对应着加载到内存中的一个运行时的类

功能

在运行时,

判断一个对象所属的类

构造一个类的对象

判断类具有的成员变量和方法

获取泛型信息

调用对象的成员变量和方法

处理注解

生成动态代理

普通使用

<>

通过setAccessible(true);可以获取私有的属性和方法

理解

java.lang.Class类的理解

类加载

javac.exe后会生成一个或多个字节码文件

java.exe对某个字节码文件解释运行,相当于把字节码文件加载到内存中

加载到内存中的类就成为运行时的类

此时运行中的类就作为Class的实例

加载到内存中的类会缓存一定时间,在此时间可以通过不同方式获取

类加载的过程

类的加载(load)

类的连接(link)

类的初始化(init)

java反射_第2张图片

类加载器的作用

将class文件的字节码加载到内存中,并将静态数据转化为方法区运行时数据结构

获取Class实例的方式

带泛型不用强转了

方式一:运行时的类     的属性.class

Class clazz1=Person.class;

方式二:运行时类的对象    的方法getClass()

Class clazz2=p.getClass();

方式三:调用Class的静态方法:forName(String classPath)

Class clazz3=Class.forName("全类名");

方式四:使用类的加载器

ClassLoader classloader=RefectionTest.class.getClassLoader();

class clazz4=classloader.loadClass("全类名")

注意:clazz1==clazz2==clazz3==clazz4

哪些类型可以有Class对象

外部内部各种类

接口

数组(数组的元素和类型一样,产生的Class对象就==)

枚举

注解

基本数据类型

甚至是void和Class本身

创建对应的运行时类的对象

newInstance会创建一个运行类的对象

运行时类必须提供空参构造器

空参构造器的访问权限得够。通常设置public

(Person)clazz.newInstance();  //用泛型就不需要转了

这里是直接用clazz.new。之前的例子是先用getConstructor

获取运行时类的完整结构

可以看看视频:https://www.bilibili.com/video/BV1Kb411W75N?p=650

获取属性结构

Field[] F=clazz.getFields();获取当前运行时类及父类所有public的属性

Field[] F=clazz.getDeclaredFileds();获取当前运行时类的所有属性(不包含父类,能获取私有)

f=F[0];获取一个属性

int m=f.getModifiers();获取权限修饰符,返回int     可以用Modifier.toString(m)翻译成文字

Class type=f.getType();type.getName();获取属性的类型

String name=f.getName();获取属性的名字

获取方法结构

Method[] M=clazz.getMethods();获取当前运行时类及父类所有public的方法

Method[] M=clazz.getDeclaredMethods();获取当前运行时类的所有属性(不包含父类,能获取私有)

m=M[0];获取一个方法,权限修饰符/返回值类型/方法名/参数/throws/注解

Annotation[] annos=m.getAnnotations();

Modifier.toString(m.getModifiers());获取权限修饰符

m.getReturnType().getName();获取返回值

m.getName()获取方法名,可以和下面的形参组合使用

Class[] pars=m.getParameterTypes();拿到形参

Class[] es=m.getExceptionTypes();拿到异常

获取构造器

Constructor[] cons=clazz.getConstructors();获取当前运行时类中public的构造器

Constructor[] cons=calzz.getDeclaredConstructors();获取当前运行时类中所有的构造器

获取类

Type type=clazz.getSuperclass();获取父类

Type Ttype=clazz.getGenericSuperclass();获取带泛型的父类

获取父类的泛型

java反射_第3张图片

获取运行时类实现的接口

class[] interfaces=clazz.getInterfaces();

获取运行时类指定的属性/方法

获取属性

非静态要有运行时对象Person p=(Person)clazz.newInstance()

Field name=clazz.getField("name");

name.set(p,"wang")设置哪个对象的name,设置成什么

获取私有

Field name=clazz.getDeclaredField("name");

name.setAccessible(true);设置这个才能set

name.set(p,"wang")

获取方法

Person p=(Person) clazz.newInstance();

Method show=clazz.getDeclaredMethod("show",String.class);指定方法,形参

show.setAccessible(true);

Object reV=show.invoke(p,"jian")方法的调用者,方法的形参值

invoke()方法的返回值即调用方法的返回值

调用静态方法

show.invoke(Person.class,"jian");其实写null也可以

调用指定的构造器

Constructor cons=clazz.getDeclaredConstructor(String.class)

cons.setAccessible(true);

Person p=cons.newInstance("");

你可能感兴趣的:(#,java,java,jvm,开发语言)