Java 类型信息
《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 类型信息的更多相关文章
- JAVA类型信息——反射机制
JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...
- JAVA类型信息——Class对象
JAVA类型信息——Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...
- Java基础 -- 深入理解Java类型信息(Class对象)与反射机制
一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...
- Java类型信息
一.引言 最近在阅读<Java编程思想>,学习一下java类型信息,现在做一下总结.Java如何让我们在运行时识别对象和类的信息的.主要有两种方式:一种是传统的“RTTI”,它假定我们在编 ...
- JAVA类型信息——Class对象(转载)
JAVA类型信息--Class对象 一.RTTI概要 1.类型信息RTTI :即对象和类的信息,例如类的名字.继承的基类.实现的接口等. 2.类型信息的作用:程序员可以在程序运行时发现和使用类型信息. ...
- Thinking in Java -- 类型信息RTTI
Thinking in Java – 类型信息 个人感觉 java 中的比較难的部分了,在看了些netty源代码发现事实上这块很实用. 这章重点是RTTI和反射.先说下自己的理解 RTTI是执行时识别 ...
- Java类型信息(RTTI和反射)
要想在IT领域站得住脚,必须得不断地学习来强化自己,但是学过的技术不实践很容易便被遗忘,所以一直都打算开个博客,来记录自己学的知识,另外也可以分享给有需要的人! 最近在学习反射,为了更好地理解反射,就 ...
- Java 类型信息 —— 获取泛型类型的类对象(.class)
How to get a class instance of generics type T 考虑泛型类Foo<T>,在其成员中,如果想获取类型(type)T的类实例(class inst ...
- Java 类型信息详解和反射机制
本文部分摘自 On Java 8 RTTI RTTI(RunTime Type Information)运行时类型信息,能够在程序运行时发现和使用类型信息,把我们从只能在编译期知晓类型信息并操作的局限 ...
随机推荐
- C++ STL之priority_queue
STL中的priority_queue(优先队列)是一种会按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序的容器,不同优先级的情况下,top()上永远是最高优先级的数据,其底层采用的 ...
- 编译Apache Hadoop2.2.0源代码
Hadoop2的学习资料很少,只有官网的少数文档.如果想更深入的研究hadoop2,除了仅看官网的文档外,还要学习如何看源码,通过不断的调试跟踪源码,学习hadoop的运行机制. 1.安装CentOS ...
- 设置sudo不输入密码 sudoers 编辑出错后的补救方法
一 设置sudo为不需要密码 有时候我们只需要执行一条root权限的命令也要su到root,是不是有些不方便?这时可以用sudo代替.默认新建的用户不在sudo组,需要编辑/etc/sudoers文件 ...
- 用canvas实现图片滤镜效果详解之视频效果
这是一个很有意思的特效,模拟摄像机拍摄电视屏幕画面时出现点状颗粒的效果.颗粒的大小通过变换矩阵实现,可以任意调节,有兴趣研究的朋友可以尝试更多的效果,代码没有经过优化,只是一个粗糙的Demo,大家可以 ...
- Java 图片转换为字符图 CharMaps (整理)
/* * Java 图片转换成字符图 CharMaps (整理) * * 2016-1-2 深圳 南山平山村 曾剑锋 * * @(#)CharMaps.java 2014/1/16 * 1.这个一 ...
- 中文分词系列(一) 双数组Tire树(DART)详解
1 双数组Tire树简介 双数组Tire树是Tire树的升级版,Tire取自英文Retrieval中的一部分,即检索树,又称作字典树或者键树.下面简单介绍一下Tire树. 1.1 Tire树 Trie ...
- 【解题报告】[动态规划] CodingTrip - 携程编程大赛 (预赛第一场)- 聪明的猴子
原题: 聪明的猴子 Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Problem D ...
- Android AIDL SERVICE 双向通信 详解
http://www.cnblogs.com/punkisnotdead/p/5062631.html 起因 是这个blog 提到了 用webview 的时候 用开启子进程的方式 可以极大避免内存泄露 ...
- windows xp 安装mysql5.6.17-ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password
.zip解压后没有setup 没有my.ini 1.安装方法 bin目录下执行以下: E:\mysql-5.6.17-win32\bin>mysqld install MySQL --defau ...
- IE6对CSS支持Bug收集
1.IE6双外边距 在IE6下,如果对元素设置了浮动,同时又设置了margin-left或者margin-right,margin值会加倍. 例如,设置margin-left:10px在IE6下会显示 ...