登陆

十分钟把握Java高档开发—反射

admin 2019-10-31 211人围观 ,发现0个评论

点击上方☝Java编程技术乐土,轻松重视!及时获取风趣有料的技术文章

做一个活跃的人

编码、改bug、提高自己

我有一个十分钟把握Java高档开发—反射乐土,面向编程,春暖花开!

作者:rocomp

链接:www.cnblogs.com/rocomp/p/4781987.html

了解反射对学习Java结构有很大的协助,如Spring结构的中心便是运用Java反射完成的,并且对做一些Java底层的操作会很有协助。

一、Class类的运用

1、万事万物皆目标,(当然,根本数据类型,静态成员不是面向目标(归于类的十分钟把握Java高档开发—反射)),所以咱们创立的每一个类也都是目标,即类自身是java.lang.Class类的实例目标,可是这些目标都不需求new出来,由于java.lang.Class类的结构办法是私有的

2、任何一个类都是Class类的实例目标,这个实例目标有三种表明办法:(咱们新建一个Student类)

  1. Class c1 = Student.class;//实践告知咱们任何一个类都有一个隐含的静态成员变量class(知道类名时用)
  2. Class c2 = stu.getClass();//已知该类的目标经过getClass办法(知道目标时用)
  3. Class c3 = Class.forName("类的全名");//会有一个ClassNotFoundException反常

官网解说说:c1,c2表明了Student类的类类型()class type),万事万物皆目标,类也是目标,是Class类的实例目标,这个目标咱们成为该类的类类型(有点乱,可是渐渐捋一下仍是能了解的)

这里有一点值得注意,当咱们履行System.out.println(c1==c2);句子,成果回来的是true,这是为什么呢?原因是不论c1仍是c2都代表了Student类的类类型,一个类可能是Class类的一个实例目标。

咱们完全能够经过类的类类型创立该类的目标实例,即经过c1或c2创立Student的实例。

Student stu = (Student)c1.newInstance();//条件是有必要要有无参的结构办法,由于该句子会去调用其无参结构办法。该句子会抛出反常。

二、动态加载类

  1. 编译时加载类是静态加载类,
  2. new 创立目标是静态加载类,在编译时间就需求加载一切可用运用到的类,假如有一个用不了,那么整个文件都无法经过编译
  3. 运转时加载类是动态加载类
  4. Class c = Class.forName("类的全名"),不只表明了类的类型,还表明了动态加载类,编译不会报错,在运转时才会加载,运用接口标准能更便利动态加载类的完成。功能性的类尽量运用动态加载,而不必静态加载。

许多软件比方QQ,360的在线晋级,并不需求从头编译文件,仅仅动态的加载新的东西

三、获取办法信息

1、根本的数据类型,void关键字都存在类类型

Class c1 =int.class;//int的类类型
Class c2 =String.class;//String类的类类型,能够了解为编译生成的那个String.class字节码文件,
//当然,这并不是官方的说法
Class c3 =double.class;
Class c4 =Double.class;
Class c5 =void.class;

2、Class类的根本API操作

/**
* 打印类的信息,包含类的成员函数,成员变量
* @param obj 该目标所属类的信息
*/
publicstaticvoid printClassMessage(Object obj){
//要获取类的信息,首要要获取类的类类型
Class c = obj.getClass();/教/传递的是哪个子类的目标,c便是该子类的类类型
//获取类的称号
System.out.println("累的称号是:"+c.getName());
/*
* Method类,办法的目标
* 一个成员办法便是一个Method目标
* getMethods()办法获取的是一切的public的函数,包含父类承继而来的
* getDeclaredMethods()获取的是多有该类自己声明的办法,不问拜访权限
*/
Method[] ms = c.getMethods();//c.getDeclaredMethods();
for(int i =0; i < ms.length; i++){
//得到办法的回来值类型的类类型
Class retrunType = ms[i].getReturnType();
System.out.print(retrunType.getName()+" ");
//得到办法的称号
System.out.print(ms[i].getName()+"(");
//获取的参数类型--->得到的是参数列表的类型的类类型
Class[] paraTypes = ms[i].getParameterTypes();
for(Class class1 : paraTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}

Class的API中还有许多其他的办法,能够得到interface、Package、Annotation等许多信息,具体运用请参阅协助手册,本文就不在具体解说。特别注意的一点是,假如你想得到一个类的信息,首要就要获取该类的类类型。

四、获取成员变量结构函数信息

/**
* 成员变量也是目标,是java.lang.reflect.Field这个类的的目标
* Field类封装了关于成员变量的操作
* getFields()办法获取的是一切public的成员变量的信息
* getDeclareFields()办法获取的是该类自己声明的成员变量的信息
*/
Field[] fs = c.getDeclaredFields();
for(Field field : fs){
//得到成员变量的类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成员变量的称号
String fieldName = field.getName();
System.out.print(typeName+" "+fieldName);
}
/**
* 结构函数也是目标
* java.lang.Constructor中封装了结构函数的信息
* getConstructor()办法获取一切的public的结构函数
* getDeclaredConstructors得到一切的结构函数
*/
Constructor[] cs = c.getDeclaredConstructors();
for(Constructor constructor : cs){
System.out.print(constructor.getName()+"(");
//获取结构函数的参数列表---》得到的是参数雷彪十分钟把握Java高档开发—反射的类类型
Class[] paramTypes = constructor.getParameterTypes();
for(Class class1 : paramTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}

五、办法反射的根本操作

  1. 怎么获取某个办法
  2. 办法的称号和办法的参数列表才干仅有决议某个办法
  3. Method m = c.getDeclaredMethod("办法名",可变参数列表(参数类型.class))
  4. 办法的反射操作
  5. m.invoke(目标,参数列表)
  6. 办法假如没有回来值,回来null,假如有回来值回来Object类型,然后再强制类型转化为原函数的回来值类型

六、经过反射了解调集泛型的实质

ArrayList list1 =newArrayList();
ArrayList list2 =newArrayList();
Class c1 = list1.getClass();
Class c2 = list2.getClass();
System.out.println(c1==c2);//成果为true,为什么??

成果剖析:由于反射的操作都是编译之后的操作,也便是运转时的操作,c1==c2回来true,阐明编译之后调集的泛型是去泛型化的。

那么咱们就能够了解为,Java调集中的泛型,是用于避免过错类型元素输入的,比方在list2中咱们add一个int,add(10)就会编译报错,那么这个泛型就能够只在编译阶段有用,经过了编译阶段,泛型就不存在了。能够验证,咱们绕过编译,用反射动态的在list2中add一个int是能够成功的,仅仅这时由于list2中存储了多个不同类型的数据(String型,和int型),就不能用for-each来遍历了,会抛出类型转化过错反常ClassCastException

弥补材料:

七、关于Java类加载器内容的详解

1、类的加载

当程序要运用某个十分钟把握Java高档开发—反射类时,假如该类还未被加载到内存中,则体系会经过加载,衔接,初始化三步来完成对这个类进行初始化

  • 加载:
  • 便是指将class文件读入内存,并为之创立一个Class目标,任何类被运用时体系都会树立一个Class目标
  • 衔接:
  • 验证:保证被加载类的正确性
  • 预备:担任为类的静态成员分配内存,并设置默许初始化值
  • 解析:将类中的符号引证替换为直接引证
  • 初始化:
  • 局部变量保存在栈区:有必要手动初始化
  • new 的目标保存在堆区:虚拟机遇进行默许初始化,根本数据类型初始化值为0,引证类型初始化值为null

2、类加载的机遇(只加载一次)

以下机遇仅表明第一次的时分

  1. 创立类的实例的时分
  2. 拜访类的静态变量的时分
  3. 调用类的静态办法的时分
  4. 运用反射办法来强制创立某个类或接口对应的java.lang.Class目标
  5. 初始化某个类的子类的时分
  6. 直接运用java.exe指令来运转某个主类

3、类加载器

担任将.class文件加载到内存中,并为之生成对应的Class目标

尽管咱们在开发过程中不需求关怀类加载机制,可是了解这个机制咱们就能更好的了解程序的运转

4、类加载器的组成

  1. Bootstrap ClassLoader 根类加载器
  2. 也被称为引导类加载器,担任Java中心类的加载,比方System十分钟把握Java高档开发—反射类,在JDK中JRE的lib目录下rt.jar文件中的类
  3. Extension ClassLoader 扩展类加载器
  4. 担任JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录
  5. System ClassLoader 体系类加载器
  6. 担任在JVM启动时加载来自java指令的class文件,以及classpath环境变量所指定的jar包和类途径,主要是咱们开发者自己写的类

11月18日四川省甜瓜子市场行情动态

2019-12-06
  •   光明

  • 11月18日新疆甜瓜子市场行情动态

    2019-12-06
  • 极彩娱乐-京东物流苦尽甘来 连马云也没料到!

    极彩娱乐-京东物流苦尽甘来 连马云也没料到!

    2019-12-06
  •   成都西部批发

    极彩娱乐-11月18日四川省桂圆干市场行情动态

    2019-12-06
  • 请关注微信公众号
    微信二维码
    不容错过
    Powered By Z-BlogPHP