要想在IT领域站得住脚,必须得不断地学习来强化本身,可是学过的技术不实践很容易便被遗忘,因此一直都打算开个博客,来记录本身学的知识,另外也能够分享给有须要的人!java
最近在学习反射,为了更好地理解反射,就去查各类资料学习了java类型信息。程序员
目录数组
1、前言框架
在了解java类型信息前,须要先了解咱们编写的类在Java中是如何加载的,以及Class类的基本概念和做用,以方便咱们更好理解Java类型信息。学习
2、类的加载和初始化 this
2.1 类的加载编码
当程序要使用某个类时,若是该类还未被加载到内存中,则系统会经过加载,链接,初始化三步来实现对这个类的初始化。spa
2.2 类的加载时机翻译
2.3类加载器代理
2.4 双亲委派模型
类加载器Java类如同其余的Java类同样,也是要由类加载器来加载的。除了启动类根类加载器每一个类都有其父类加载器(父子关系有组合(不是继承)来实现)。
所谓双亲委派模型是指每次收到类加载请求时,先将请求委派给父类加载器完成(全部加载请求最终会委派到顶层的Bootstrap Class Loader加载器中),若是父类加载器没法完成这个加载(该加载器的搜索范围没有找到对应的类),子类尝试本身加载。
双亲委派好处
3、Class类
Class类封装一个对象和接口的运行时的状态(即在这个类的对象中记录每一个对象所属的类,保存类的类型信息)。操做类对象在使用前会经历上文所说的加载过程(加载、裂解和初始化),并为之建立一个Class类的对象---Class对象,存放在操做类的.class文件中。这个Class类对象与操做类class是一一对应的,即当一个操做类被加载后,就不会重复加载。而经过该class对象,就能够访问对应的class。咱们能够把Class理解为一个类的标识对象,它至关因而一个类的铭牌。拿到一个Class,咱们就能够找到对应的类。
注意,Class类没有公有(public)构造方法,所以不能显式地声明一个Class对象,只在类加载时建立。
从Class对象中能够得到的信息:
另外,网上不少帖子说,一旦某个操做类的Class对象被载入内存,就用它来产生该操做类的全部对象!
获取Class对象的三种方式:
1 Dog dog; 2 Class class = dog.getClass();
1 Class class = Class.forName("Dog");
1 Class class = Dog.class;
Class类经常使用的方法:
4、Java类型信息
咱们知道,咱们的程序在运行时,某一个操做类能够回被实例化多个对象,一个程序也可能拥有若干个不一样操做类的多个对象,那么Java如何在运行时识别对象所属和类的信息的呢?答案是运行时类型信息(Run-Time Type Identification),RTTI使得你能够在程序运行时发现和使用类型信息。
1、RTTI概要
2、RTTI的实现方式
3、传统RTTI的使用
1 abstract class Shapes{ 2 void draw(){ 3 System.out.println(this+".draw()"); 4 } 5 abstract public String toString(); 6 } 7 8 class Circle extends Shapes{ 9 public String toString(){ 10 return "Circle"; 11 } 12 } 13 class Triangle extends Shapes{ 14 public String toString(){ 15 return "Triangle"; 16 } 17 } 18 class Square extends Shapes{ 19 public String toString(){ 20 return "Square"; 21 } 22 } 23 class Test{ 24 public static List<Shapes>getList(){ 25 List<Shapes> list_aShapes = Arrays.asList(new Circle,new Square,new Triangle); 26 } 27 } 28 29 public class Shape{ 30 public static void main(String args[]){ 31 List<Shapes> list_aShapes = Test.getList(); 32 for(Shapes shape:list_aShapes){ 33 shape.draw(); 34 } 35 } 36 }
运行结果:Circle.draw()
Square.draw()
Triangle.draw()
结果分析:
上面代码中,shape对象只是一个泛化引用,显然一开始系统并不知道泛华引用的确切类型,咱们但愿使用的是shape对象对应的确切类型,这是,就须要系统使用RTTI。上例,只是打印出泛化引用的全部类型。进一步解析,Circle,Square,Triangle三个类都继承了抽象类Shape,现有一个List<Shape>的数组,存的是Circle,Square.Triangle的对象,当你拿出一个对象时,你只知道她是Shape类,但不知道它的具体类型。使用RTTI,能够查询到某个shape引用所指向对象的具体类型。
4、反射机制
java反射的官方介绍是 反射机制是在运行中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性。
反射机制能作什么?
其实,咱们在学习框架时可以发现反射的普遍应用,经过反射和一个未知类型的对象打交道,Class类和java.lang.reflection类库一块儿对反射做技术支撑,该类库包含Field,Method和Constructor类,这些类的对象由JVM启动时建立,用以表示未知类里对应的成员。
关于反射的详细内容以后的文章会介绍!
5、传统RTTI和反射的共同点和区别
区别:
1、若是该类在编译前就已知。也就是该类在classPath路径下。这就是传统RTTI。
2、若是该类编译器未知,也就是在程序运行时才知道的。这就是反射
因此RTTI和反射的本质区别只是检查一个类的.class文件的时机不一样,反射:.class 文件是在编译时不可得到的,因此在运行时打开和检查未知类的.class文件从而变已知。RTTI: .class 文件是在编译时打开和检查。
相同点:都是基于Class类来执行的,均可以获取类的类型信息。
6、总述
其实你们会发现,相比于反射,咱们基本不会接触到传统RTTI机制,这是为什么呢?其实它的名字已经给出了答案,这是一个机制---传统RTTI机制,其实在Java不少地方都依赖于这个机制来实现,好比说多态(当咱们把子类对象的引用赋给父类对象的状况时,须要使用RTTI去识别该对象所属的类),因此说这并非可有可有的。咱们也能够在网上的不少文章看到,不少文章都是把RTTI分为传统RTTI和反射,以阐述java类型信息的详情,这样咱们便可以很好地学习反射,也搞清楚了Java在运行时对于对象的识别方法。