谜语大全,历史的天空,主宰之王-在线认证厨师,厨师在线资格认证,在线厨艺新闻

admin 2019-05-21 阅读:111

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

一、Class类的运用

1、万事万物皆目标,(当然,根本数据类型,静态成员不是面向目标(归于类的)),所以咱们创立的每一个类也都是目标,即类自身是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()+"(");

//获取结构函数的参数列表---》得到的是参数雷彪的类类型

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、类的加载

当程序要运用某个类时,假如该类还未被加载到内存中,则体系会经过加载,衔接,初始化三步来完成对这个类进行初始化

加载:

便是指将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类,在JDK中JRE的lib目录下rt.jar文件中的类
  3. Extension ClassLoader 扩展类加载器
  4. 担任JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录
  5. System ClassLoader 体系类加载器
  6. 担任在JVM启动时加载来自java指令的class文件,以及classpath环境变量所指定的jar包和类途径,主要是咱们开发者自己写的类

写在最终:小编为我们预备了一些适合于1-5年以上开发经历的java程序员面试涉及到的绝大部分面试题及答案做成了文档和学习笔记文件以及架构视频材料免费共享给我们(包含Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术材料),期望能够协助到我们。

获取办法:请我们转发重视并私信小编(学习)即可获取你需求的各类材料。