《Thinking in Java 4th》第14章 类型信息

运行时类型信息(Run-Time Type Identification)使得你可以在程序运行时发现和使用类型信息。

14.1 为什么需要RTTI

Circle,Square,Triangle三个类都继承自抽象类Shape,现有一个List<Shape>的数组,存的是Circle,Square,Triangle的对象,当你拿出一个对象时,你只知道它是Shape类,但不知道它的具体类型。使用RTTI,可以查询某个Space引用所指向的对象的具体类型。

14.2 Class对象

Java使用Class对象来执行其RTTI,它包含了与类有关的信息。每一个类都有一个Class对象,被保存在同名的.class文件中。为了生成这个类的对象,运行这个程序的JVM将使用被称为“类加载器”的子系统。

所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会加载这个类。因此,Java程序在它开始运行之前并未被完全加载。其各部分是在必需时才加载的。

类加载器首先检查这个类的Class对象时候已经加载,如果尚未加载,默认的类加载器就会根据类名查找.class文件。一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。

package typeinfo;

class Candy { static { System.out.println("Loading Candy"); } }

class Gum { static { System.out.println("Loading Gum"); } }

class Cookie { static { System.out.println("Loading Cookie"); } }

public class SweetShop {
public static void main(String[] args) {
System.out.println("inside main");
new Candy();
System.out.println("After create Candy");
try {
Class.forName("typeinfo.Gum");//书上没有加包名,亲测需要加
} catch (ClassNotFoundException e) {
System.out.println("Couldn't find Gum");
}
System.out.println("After Class.forName(\"Gum\")");
new Cookie();
System.out.println("After create Cookie");
}
}

typeinfo.SweetShop.java

forName()是取得Class对象引用的一种方法,包含目标类的文本名的String作为输入,返回Class对象的引用。

package typeinfo.toys;

interface HasBatteries {}
interface Waterproof {}
interface Shoots {} class Toy {
Toy() {}
Toy(int i) {}
} class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots {
FancyToy() { super(1); }
} public class ToyTest {
static void printInfo(Class cc) {
System.out.println("Class name: " + cc.getName() + " is interface? [" + cc.isInterface() + "]");
System.out.println("Simple name: " + cc.getSimpleName());
System.out.println("Canonical name: " + cc.getCanonicalName());//Canonical:规范化=_=
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("typeinfo.toys.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("Can't find FancyToy");
System.exit(1);
}
printInfo(c);
for (Class face: c.getInterfaces()) {
printInfo(face);
}
Class up = c.getSuperclass();
Object obj = null;
try {
// 需要默认构造函数 即无参的构造函数 否则会报错
obj = up.newInstance();
} catch (InstantiationException e) {
System.out.println("Cannot instantiate");
System.exit(1);
} catch (IllegalAccessException e) {
System.out.println("Cannot access");
System.exit(1);
}
printInfo(obj.getClass());
}
}

typeinfo/toys/ToyTest.java

通过对象.getClass()可以直接得到Class引用。

可以看到Class包含很多有用的方法。可以得到接口信息,父类信息,以及类名等。

newInstance()创建的类,必须带有默认构造器。

练习10.编写一个java程序,用来判断一个char数组是个基本类型还是个对象?

属于对象,Java基本类型只有 boolean, byte, short, char, int, long, float, double 8种,Java中数组都是对象。

package typeinfo;

public class Exercise10 {
public static void main(String[] args) {
char[] ch = new char[10];
Class cc = ch.getClass();
typeinfo.toys.ToyTest.printInfo(cc);
System.out.println(ch instanceof Object);
}
}
/**
Class name: [C is interface? [false]
Simple name: char[]
Canonical name: char[]
true
*/

Exercise10

14.2.1 类字面常量

通过类名.class也可以得到Class对象的引用。当使用".class"来创建对Class对象的引用时,不会自动地初始化该Class对象。

基本类型.class = 基本类型的包装类.class

package typeinfo;

import java.util.*;

class Initable {
static final int staticFinal = 47;
static final int staticFinal2 = ClassInitialization.rand.nextInt(1000);
static { System.out.println("Initializing Initable"); }
} class Initable2 {
static int staticNotFinal = 147;
static { System.out.println("Initializing Initable2"); }
} class Initable3 {
static int staticNotFinal = 74;
static { System.out.println("Initializing Initable3"); }
} public class ClassInitialization {
public static Random rand = new Random(47);
public static void main(String[] args) throws Exception {
Class initable = Initable.class;
System.out.println("After create Initable ref");
System.out.println(initable.isInterface());
System.out.println(Initable.staticFinal);
System.out.println(Initable.staticFinal2);
System.out.println(Initable2.staticNotFinal);
Class initable3 = Class.forName("typeinfo.Initable3");
System.out.println("After create Initable3 ref");
System.out.println(Initable3.staticNotFinal);
} }

typeinfo/ClassInitialization.java

如果一个static final是“编译期常量”,那个这个值不需要对类初始化就可以读取。

14.2.2 泛化的Class引用

例: Class<Integer> intClass = int.class;

使用Class<?>优于Class。

向Class添加泛型是为了提供编译期类型检查。

感觉Java的泛型真神奇啊(= =)

Class<? extends T> 我也就忍了 竟然还有 Class<? super T> up = TObj.getSuperclass();

Object obj = up.newInstance(); <-- 得到的只是Object

14.2.3 新的转型语法

按作者的意思,这个并没有什么用……

package typeinfo;

class Building {}
class House extends Building {} public class ClassCasts {
public static void main(String[] args) {
Building b = new House();
Class<House> houseType = House.class;
House h = houseType.cast(b);
h = (House)b; // ... or just do this.
}
}

typeinfo/ClassCasts.java

14.3 类型转换前先做检查

如果你想向下转型,先用关键字instanceof检查

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

//我发现作者有一种神奇的能力——把很简单的事情写成一大堆神烦的代码……就算写代码少写几行不行吗啊魂淡……一定是按字数付稿费……

//我把那一堆代码抄完我都懒得复制过来了,头疼= =

使用 a instanceof AClass 就必须写AClass的类名。但是没有储存类名的容器呀,所以就想到改进方法,使用Class对象,然后使用它的Class对象.isInstanceof(目标对象)就可以辣!

isAssignableFrom   是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。

通常调用格式是 :  Class1.isAssignableFrom(Class2)

14.4 注册工厂

没看懂(捂脸 先过……

14.5 instanceof 与 Class 的等价性

a instanceof B 等价于 B.class.isInstance(a) 当对象a的类型与B相同或者是其派生类时,返回true

a.getClass()==B.class 等价于 a.getClass.equals(B.class) 当且仅当对象a的类型与B相同时,返回true

14.6 反射:运行时的类信息

RTTI和反射之间真正的区别只在于,对RTTI来说,编译器在编译时打开检查.class文件。而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开时和检查.class文件。

Class<?> c = Class.forName(args[0]);
Method[] methods = c.getMethods();
Constructor[] ctors = c.getConstructors();

args[0]在编译时是不可知的,但是通过反射,你可以知道类中的方法以及构造器。

事实上反射可以获得类的所以域和方法,甚至包括private。

设计模式什么的,真的看不懂啊~~~>_<~~~

Java 类型信息的更多相关文章

  1. JAVA类型信息——反射机制

    JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...

  2. JAVA类型信息——Class对象

    JAVA类型信息——Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...

  3. Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

    一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...

  4. Java类型信息

    一.引言 最近在阅读<Java编程思想>,学习一下java类型信息,现在做一下总结.Java如何让我们在运行时识别对象和类的信息的.主要有两种方式:一种是传统的“RTTI”,它假定我们在编 ...

  5. JAVA类型信息——Class对象(转载)

    JAVA类型信息--Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...

  6. Thinking in Java -- 类型信息RTTI

    Thinking in Java – 类型信息 个人感觉 java 中的比較难的部分了,在看了些netty源代码发现事实上这块很实用. 这章重点是RTTI和反射.先说下自己的理解 RTTI是执行时识别 ...

  7. Java类型信息(RTTI和反射)

    要想在IT领域站得住脚,必须得不断地学习来强化自己,但是学过的技术不实践很容易便被遗忘,所以一直都打算开个博客,来记录自己学的知识,另外也可以分享给有需要的人! 最近在学习反射,为了更好地理解反射,就 ...

  8. Java 类型信息 —— 获取泛型类型的类对象(.class)

    How to get a class instance of generics type T 考虑泛型类Foo<T>,在其成员中,如果想获取类型(type)T的类实例(class inst ...

  9. Java 类型信息详解和反射机制

    本文部分摘自 On Java 8 RTTI RTTI(RunTime Type Information)运行时类型信息,能够在程序运行时发现和使用类型信息,把我们从只能在编译期知晓类型信息并操作的局限 ...

随机推荐

  1. 【MySQL】ERROR 1045 (28000): Access denied for user的解决方法

    去官网下载压缩版的MySQL Server,解压配置path环境变量后.然后克隆my-default.ini创建my.ini文件,在文件中[mysqld]下面配置basedir和datadir bas ...

  2. RIA技术

    Rich Internet Application(富互联网应用程序,简称RIA),一种全新的Web应用程序架构,它结合了桌面软件良好的用户体验和web应用程序易部署的优点,很快获得了企业的青睐. 近 ...

  3. Machine Learning for hackers读书笔记(六)正则化:文本回归

    data<-'F:\\learning\\ML_for_Hackers\\ML_for_Hackers-master\\06-Regularization\\data\\' ranks < ...

  4. 用Maven插件生成Mybatis代码

    现在代码管理基本上是采用Maven管理,Maven的好处此处不多说,大家用百度搜索会有很多介绍,本文介绍一下用Maven工具如何生成Mybatis的代码及映射的文件. 一.配置Maven pom.xm ...

  5. 漫游Kafka实现篇之消息和日志

    消息格式 消息由一个固定长度的头部和可变长度的字节数组组成.头部包含了一个版本号和CRC32校验码. /** * 具有N个字节的消息的格式如下 * * 如果版本号是0 * * 1. 1个字节的 &qu ...

  6. cookie随便写的一点笔记(抄书的)

    cookie是保存在客户端的文本,能够在一定程度上提高用户体验.Servlet API 中提供了Cookie类,可以创建Cookie对象,并通过响应中的addCookie方法,将cookie保存到客户 ...

  7. BZOJ 4690 Never Wait for Weights

    带权并查集23333333 注意dis[x]+=dis[fath[x]. #include<iostream> #include<cstdio> #include<cst ...

  8. HDU 5319 Painter (模拟)

    题意: 一个画家画出一张,有3种颜色的笔,R.G.B.R看成'\',B看成'/',G看成这两种的重叠(即叉形).给的是一个矩阵,矩阵中只有4种符号,除了3种颜色还有'.',代表没有涂色.问最小耗费多少 ...

  9. 用于分类的决策树(Decision Tree)-ID3 C4.5

    决策树(Decision Tree)是一种基本的分类与回归方法(ID3.C4.5和基于 Gini 的 CART 可用于分类,CART还可用于回归).决策树在分类过程中,表示的是基于特征对实例进行划分, ...

  10. 国内YUM源收集

    1. 企业贡献: 搜狐开源镜像站:http://mirrors.sohu.com/网易开源镜像站:http://mirrors.163.com/ 阿里云开源站:http://mirrors.aliyu ...