《Thinking in Java》学习笔记——14章类型信息

Class对象

1.每当编写并编译了一个新类,就会产生一个Class对象(更恰当地说,是被保存在一个同名的.class文件中)。为了生成这个类的对象,运行这个程序的Java虚拟机将使用被称为“类加载器”的子系统。
2.所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这个证明构造器也是类的静态方法,因此使用new操作符创建类的新对象也会被当作对类的静态成员的引用。
3.Java程序在它开始运行之前并非被完全加载,其各个部分是在必需时才加载的
4.Class对象仅在需要的时候才被加载,static初始化是在类加载时进行的
5.无论如何,只要你想在运行时使用类型信息,就必需首先获得对恰当的Class对象的引用。Class.forName()就是实现此功能的便捷途径,因为你不需要为了获得Class引用而持有该类型的对象。如果已经拥有了一个类型的对象,那就可以通过调用getClass()方法来获取Class引用
6.getName()来产生全限定的类名;getSimpleName()来产生不含包名的类名;getCanonicalName()来产生全限定的类名;isInterface()方法可以告诉你这个Class对象是否表示一个接口;getInterfaces()方法返回的是Class对象,它们表示在Class对象中所包含的接口;getSuperclass()方法可用来查询基类,将返回用来进一步查询的Class对象;newInstance()可用来创建Class对象所对应的类,但必须带有默认构造器

一.类字面常量

1.Java还可以使用类字面常量——“.class”的形式来生成对Class对象的引用。
2.类字面常量不仅可以应用于普通的类,也可以应用于接口、数组以及基本数据类型。
3.与通过Class中的方法创建对Class对象的引用不同的是,通过“.class”的方法创建不会自动地初始化该Class对象,初始化被延迟到了对静态方法(包括构造器)或者非常数静态域进行首次引用的时候才会执行
4.使用类需要包括的三个步骤:
(1).加载,这是由类加载器执行的。该步骤将查找字节码,并从这些字节码中创建一个Class对象。
(2).链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个创建的对其他类的引用。
(3).初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。
5.如果一个static final值是“编译期常量”,那么这个值不需要对类进行初始化就可以被读取。如果一个static域不是final的,那么在对它访问时,总是要求在它被读取之前,要先进行链接(为这个域分配存储空间)和初始化(初始化该存储空间)。

class Initable {
    static final int staticFinal = 47;//static final的编译期常量,使用时不用初始化
    static final int staticFinal2 = ClassInitaialization.rand.nextINt(1000);//虽然是static final的,但是不是编译期常量,使用时需要初始化
    static int staticFinal3 = 47;//不是final的,使用时需要进行初始化
}
二.泛化的Class引用

1.Class引用表示的就是它所指向的对象的确切类型,而该对象便是Class类的一个对象。
2.使用泛型语法,实现对Class引用所指向的Class对象的类型进行限定。

public class GenericClassReference {
    public static void main(String...args) {
        Class intClass = int.class;
        Class<Integer> genericIntClass = int.class;
        genericIntClass = Integer.class; // Same thing
        intClass = double.class; // Success
        //genericIntClass = double.class; // Illegal
    }
}

为了在使用泛化的Class引用时放松限制,可以使用通配符。

Class<?> intClass = int.class;
intClass = double.class;

3.当将泛型语法用于Class对象的时候:newInstance()将返回该对象的确切类型,而不仅仅只是基本的Object

三.新的转型语法

1.JavaSE5中添加了用于Class引用的转型语法,即cast()方法:

Building b = new House();
Class<House> houseType = House.class;
House h = houseType.cast(b); // 与 h = (House) b; 效果相同

类型转换前先做检查

1.使用关键字instanceof,它返回一个布尔值,告诉我们对象是不是某个特定类型的实例:

if (x instanceof Dog)
    ((Dog) x).bark();

进行向下转型前,如果没有其他信息告诉你对象是什么类型,那么使用instanceof是非常重要的,否则会得到一个ClassCastException异常。
2.对instanceof有比较严格的限制:只可将其与命名类型进行比较,而不能与Class对象作比较。如果程序中编写了许多的instanceof表达式,就说明你的设计可能存在瑕疵。

一.动态的instanceof

1.isInstance()方法不用与命名类型进行比较,而可以直接与Class对象进行比较

Pet pet = new Dog();
if (pet.isInstance(Dog.class)))
    ((Dog) pet).bark();

2.使用isAssignableFrom()来执行运行时检查,以校验你传递的对象确实属于我们感兴趣的继承结构。

二.instanceof与Class的等价性

1.在查询类型信息的时候,以instanceofisInstance()的形式与直接比较Class对象有一个很重要的区别。instanceof保持了类型的概念,它指的是“你是这个类吗,或者你是这个类的派生类吗?”而如果用“==”比较实际的Class对象,就没有考虑继承——它或者是这个确切的类型,或者不是

反射:运行时的类信息

1.Class类与java.lang.reflect类库一起对反射的概念进行了支持,该类库包括了FieldMethod以及Constructor类(每个类都实现了Member接口)。这些类型的对象是由JVM在运行时创建的用以表示未知类里对应的成员。
2.RTTI和反射之间真正的区别只在于,对RTTI来说,编译器在编译时打开和检查.class文件。而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件。

类方法提取器

1.ClassgetMethods()getConstructors()方法分别返回Method对象的数组和Constructor对象的数组。
2.Class.forName()生成的结果在编译时是不可知的,因此所有的方法特征签名信息都是在执行时被提取出来的。反射机制提供了足够的支持,使得能够创建一个编译时完全未知的对象,并调用此对象的方法。

接口与类型信息

1.通过使用反射,即使实现包的访问权限,仍旧可以到达并调用所有方法,甚至是private方法。如果知道方法名,就可以在其Method对象上调用setAccessible(true),然后通过invoke()方法来使用该方法。
2.final域实际上在遭遇修改时是安全的。运行时系统会在不抛异常的情况下接受任何修改尝试,但实际上不会发生任何修改。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,103评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 6,943评论 0 62
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,584评论 0 11
  • 牵着小狗漫步在初春的街道上,随处可见青绿的嫩冬青,当然我并不知道它是不是冬青,只是感觉像罢了。我忍不住想去摘下一...
    与你北郊阅读 328评论 0 0