笔记思路:整理的文章全面重点,有些已经理解的含义只是简单提起,不太好理解的进行重点总结。主要是建立一个框架
14.1 RTTI & 14.2Class对象
RTTI:Run-Time Type Identification
运行时类型信息使得我们可以在程序运行时发现和使用类型信息
类是程序的一部分,每个类都有一个Class对象,每当编写并编译了一个新类,就会产生一个class对象(保存在一个同名的.class文件中),JVM此时会使用被称为"类加载器"子系统。
Java程序在它开始运行之前并非完全加载,当程序创建第一个对类的静态成员的引用时,才会加载这个类。
过程:类加载器首先检查这个类的class对象是否已经加载,如果尚未加载,默认的类加载器就会根据类名查找class对象。
paf书中的350页有具体解释
Class.forName()方法
输入:包含目标类的文本名的String作为输入参数,必须是全限定名
输出:一个Class对象的引用
如果找不到,会抛出ClassNotFoundException异常。
getName()
产生全限定类名
getSimpleName()
产生不包含包名的类名
getCanoicalName()
isINterface()
返回Class对象,在Class对象中所包含的接口
getInterfaces
getClass()
Class.getInterClass
getSuperClass
查询基类
newInstance()
返回该对象的确切类型,使用它来创建的类必须带有默认的构造
instanceof
判断是否为实例 只能与命名类型比较,不能与Class对象比较。 isinstance可以替代它
14.2.1 类字面常量
另一种方法对于Class对象的引用,但不会自动初始化该Class对象。初始化被延迟到了对静态方法,或者非常数静态域进行首次引用时执行。
但Class.forName()立即进行了初始化。
若static final 是编译器常量,那么该值不需要对Initable类进行初始化就可以被读取。
若static 域不是final的,那么在它被读取之前,要先进行链接(分配储存空间)和初始化(初始化该存储空间)。
14.2.2 泛化的Class类引用
泛型类引用只能赋值为其指向其声明的类型,普通类引用可以被重新赋值为指向任何其他的class对象。
Class<? extends Number> bounded =int.Class();
Class<? super FancyToy> //某个类,它是FancyToy的超类
泛型语法中的Class对象,使用 newInstance()会返回该对象的确切类型。
14.2.3 新的转型语法
JavaSE5 cast()方法,
House h =houseType.cast(b);//接收参数对象,并将其转型为Class引用的类型
对于无法使用普通转型的情况非常有用
14.3 类型转换前先做检查
RTTI的三种形势:
1.传统的类型转换
2.代表对象类型的Class对象
3.关键字instanceOf,返回布尔值,告诉我们对象是不是某个特定类型的实例
14.3.1 使用类字面常量
在PetCount方面有着非常好的实例方法,书P360
14.3.2 动态的instanceof
14.3.3 递归计数
Class1.isAssignableFrom(Class2) 校验传递的对象Class1与Class2对象所表示的接口或类相同;Class1是否是Class2的父类或者父接口。如果相同返回true,如果不相同返回false。
介绍了net/mindview/util/TypeCounter.java方法
14.4注册工厂
工厂方法设计模式
14.5 instanceof 与Class的等价性
instanceof 和 isInstance() 在判断是否是从属实例上没有较大差别,指的是“你是这个类,或是这个类的派生类吗?”
用==比较的Class 没有考虑继承 “你是这个类或者不是”
14.6 反射:运行时的类信息
Class 和 java.lang.reflect 库一起对反射的概念进行了支持。包含了Field、Method、Constructor类.(每个类都实现了Member接口)。这些类型的对象是由JVM在运行时创建的,用以标识位置类里对应的成员。这样你就可以使用Constructor创建新的对象,用get()和set()方法读取和修改与Field()对象关联的字段,用invoke()方法调用与Method对象关联的方法。还可以调用getFields()、getMethods()和getConstructors()等方法。
getMethods()获取的是所有public方法,包括:类自身声明的public方法、父类中的public方法、实现的接口方法。
getConstructors() 获取构造器
RTTI与反射的区别在于:
- RTTI,编译器在编译时打开和检查.class文件
- 反射机制,.class文件在编译时是不可获取的,在运行时打开和检查.class文件
14.6.1 类方法提取器
通过反射创建对象
- 通过类对象调用newInstance()方法,适用于无参构造方法
String.class.newInstance()
Solution solution = Solution.class.newInstance();
Solution solution2 = solution.getClass().newInstance();
Class solutionClass = Class.forName("Solution");
Solution solution3 = (Solution) solutionClass.newInstance();
- 通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,适用于无参和有参构造方法。
String.class.getConstructor(String.class).newInstance("Hello");
Solution solution =
Solution.class.getConstructor(classes).newInstance("hello1", 10);
System.out.println(solution.str); // hello1
Solution solution2 =
solution.getClass().getDeclaredConstructor(String.class).newInstance("hello2");
System.out.println(solution2.str); // hello2