引出反射和什么是反射?
问题1:
对象有编译类型和运行类型Object obj = new java.util.Date();
编译类型: Object
运行类型: java.util.Date
需求: 通过obj对象,调用java.util.Date类中的toLocaleString方法.
obj.toLocaleString(); 此时编译报错, 编译时,会检查该编译类型中是否存在toLocaleString方法. 如果存在,编译成功,否则编译失败.
解决方案:,因为obj的真实类型是java.util.Date类,所以我们可以把obj对象强制转换为java.util.Date类型.java.util.Date d = (java.util.Date)obj; d.toLocaleString();//调用成功
如果不知道obj的真实类型,就不能强转.(底层有一个方法,返回一个Object类型的java.util.Date对象).
此时问题如何解决?
- 问题2:
我在面向对象中提及到,一切事物都可以看成是对象,那么问题来了,类这种事物是啥对象呢?又使用什么类来表示类这种对象呢?
- Class类: 用来描述类或者接口的类型,描述类的类.
- Class类的实例: 在JVM中的一份份字节码,Class实例表示在JVM中的类或者接口,枚举是一种特殊的类,注解是一种特殊的接口.
- 当程序第一次使用某一个java.util.Date类的时候,就会把该类的字节码对象加载进JVM,并创建出一个Class对象.
此时的Class对象就表示java.util.Date的字节码. - Class类可以表示N个类的字节码对象,问题,到底怎么区分Class类此时表示的那一个类的字节码呢?
- 为了解决该问题,Class类的设计者提供了泛型.—>Class.
- java.lang.String类的字节码类型: Class
什么是反射:
- 反射是什么呢?当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻,
- 举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,
- 假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName(“com.java.dbtest.TestConnection”);通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。这时候就可以看到反射的好处了,这个动态性就体现出java的特性了!
- 举多个例子,大家如果接触过spring,会发现当你配置各种各样的bean时,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。
如何创建Class对象,如何来表示一个字节码对象?
//需求:获取java. util. Date类的字节码对象
//方式1:使用class属性
Class<java.util.Date> clzl = java.util.Date.class;
//方式2 :通过对象的getClass方法莱获取,getClass是Object类中的方法 java.u5il.Date date = new java.util.Date();
Class<?> clz2 = date.getClass();
//方式3:通过Class类中的静态方法forName (String className); Class<?> clz3 = Class.forName("java.util.Date");
Class<?> clz3 = Class.forName("java.util.Date");
- 注意:同一个类在JVM中只存在一份字节码对象,也就说上述,claz1 == clz2 == clz3;
- 以后使用最多的是第三种,在框架中大量使用.
存在的问题
如何表示基本类型的字节码对象呢?
- 基本数据类型不能表示为对象,也就不能使用getClass的方式,
- 基本类型没有类名的概念,也不能使用Class.forName的方式,
如何表示基本类型的字节码对象呢?
所有的数据类型都有class属性.
Class clz = 数据类型.class;
九大内置Class实例: JVM中预先提供好的Class实例,
分别:byte,short,int,long,float,double,boolea,char,void.
表示:byte.class,short.class,int.class,….void.class.在8大基本数据类型的包装类中,都有一个常量:TYPE,用于返回该包装类对应基本类的字节码对象.
System.out.println(Integer.TYPE == int.class);//true注意:Integer和int是不同的数据类型
System.out.println(Integer.class == int.class);//false
数组的Class实例:数组是引用数据类型,数组其实是对象.
如何来表示数组的Class实例.
方式1: 数组类型.class;
方式2: 数组对象.getClass();
注意:所有的具有相同的维数和相同元素类型的数组共享同一份字节码对象,和元素没有关系.小结:
- Class: 描述所有的类型,所以Class类中应该具有所有类型的相同的方法.
- Object: 描述所有的对象,所以在Object类中应该具有所有对象的共同的方法.
参考博客:
- 深入解析Java反射(1) - 基础