阅读笔记[2] ——《Think In Java》 Chapter 14 (1)

阅读笔记[2] ——《Think In Java》 Chapter 14 (1)


本章主要问题:运行时识别对象和类的信息。主要有两种方法:传统的RTTI;反射机制。

此博文先介绍传统的RTTI。

  • RTTIRuntime type identification): 在运行时识别一个对象的类型

  • Class 对象就是用来创建类的所有的“常规”对象的。类是程序的一部分,每个类都有一个 Class 对象。每当编写并且编译了一个新类,就会产生一个 Class 对象(更确切的说,是被保存在一个同名的 .class 文件中)

  • JVM 的类加载器子系统,类加载器会对类进行按需加载,如果尚未加载就会根据类名查找 .class 文件。在这个类的字节码被加载时,它们会接受验证,以确保没有被破坏,并且不包含不良的 Java 代码(安全防范目的的措施之一

  • Class 类中的常用方法

方法作用
Class.forName()如果类(参数)没有被加载就加载它,它返回一个Class对象,包含类的信息
对象.getInterfaces()返回一个Class对象(数组),包含感兴趣的class对象中所实现的接口
对象.getSuperclass()返回一个Class对象,有关父类的信息
对象.newInstance()()虚拟构造器,“我不知道你的确切类型,但是无论如何要正确地创建你自己”,需要被创建的类中有默认的构造器
对象.getName()全限定的类名
对象.getSimpleName()只是类名
对象.getCanonicalName()同getName()
对象.getDeclaredFields()获取类中的域

  • 递归打印出参数对象所在的递归体系,如下
    这里写图片描述

  • 类字面常量,它在编译时就会得到检查,故更安全高效、不需要使用 try

  • 类字面常量,不仅可以应用于普通的类,也可以应用于接口、数组以及基本数据类型。另外对于基本数据类型的包装器类,还有一个标准字段 TYPE

  • 注意:使用“.class”来创建 Class 对象的引用时,不会自动初始化该 Class 对象,有如下三个步骤:

    • [1] 加载;
    • [2] 链接;
    • [3]初始化,初始化被延迟到对静态方法(包含构造方法)或者非常数静态域进行首次引用的时候才会执行;说明:对于常数静态域是指带静态常量(final static),特例对于需要运行时赋值的(比如随机函数 P[319])不属于[编译期常量]
  • 思考对于 Class.forName() 的对类的初始化到底进行到了哪一个程度? 经过测试可得:对于对应类中的静态初始化子句已经执行,而实例初始化子句没有执行,更不用说其构造方法了

  • 使用 Class 引用的习惯(为了提供编译期的类型检查):

    • a) 利用泛化的 Class 引用可以让编译器强制执行额外的类型检查!(P320)

    • b) 如果想稍微放松一些限制,比如想限制在由一个父类继承下来的,不能直接使用其父类进行定义(Class < Number > genericNumberClass = Integer.class),因为 Integer Class 对象不是 Number Class 对象的子类;

    • c) 对于上述问题,可以使用通配符进行解决,比如 Class < ? Extends Number >。并且Class < ? > 要优于 Class,即便它们是等价的,Class < ? > 的好处是它表示并非碰巧或者由于疏忽,而使用了一个具体的类的引用,你就是选择了非具体的版本;

    • [其实这些内容应该为泛型的!]
  • 有趣的现象:当使用泛型语法用于 Class 对象时,newInstance() 将返回该对象的确切类型,而不仅仅只是 Object 。但是有种限制:如果手头的是超类,那编译器将只允许你声明超类引用是“某个类,它是 FancyToy 超类”,而此时再次使用 newInstance() 返回值不是精确类型,而只是 Object(如下):[具体原因见下章]
    这里写图片描述

  • Class 对象的 cast() 新方法,具体讨论在[第15章]

  • 类型转换:

    • a) 传统的类型转换,由 RTTI 来确保转换的正确性,如果失败会抛出一个 ClassCastException 异常;

    • b) 通过 Class 对象可以获取运行时所需的信息;

    • c) 使用关键字 instanceof,它会返回一个布尔值;

  • 小知识:

    • a) throw new RuntimeException(e); //catch 里面,在这里不知道如何处理该异常,所以就通过不必捡把它一层一层往上抛,直到结束;

    • b) Collections.addAll(list,相应数组); //利用 Collection 类来填充 list

    • c) @SuppressWarnings(“unchecked”) //告诉编译器对被批注的代码元素内部的某些警告保持静默,unchecked 指的是这里的强制转换;

    • d) (P326) 对于里面的静态内部类:需要一个功能,但是这里通过继承又不太好,故可以使用静态内部类来实现,还有要学会使用 HashMap < Object,Object > ;

  • Instanceof 有比较严格的限制:只可将其与命名类型进行比较,而不能与 Class 对象做比较。这并不是一个很好地限制。假如程序中编写了许多的 instanceof 表达式,就说明设计有缺陷 [这里可以使用动态的instanceof(P329) ]

  • 关于 Collection.unmodifiableList(List) 其返回一个等同于参数 List 的列表但是不可以对其进行修改,用处:比如,在一个学生类中有一个关于已选课的列表,如果该类不加限制的返回该列表会在不知不觉中被修改,这是可以使用该方法来是的获取的列表不可更改

  • 动态的 instanceof —— Class.isInstance ,注意在使用的时候需要获取全部的继承类(可以使用 LinkedHashMap < Class < ? extend … > ,Integer>
    这里写图片描述

  • Class 对象 .isAssignableFrom() //当调用对象是参数的超类或超接口或同一个返回为true

感觉写得有点乱:第一次读 《Think In Java》,就这样吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值