JAVA类型信息——Class对象

一、RTTI概要

1、类型信息RTTI :即对象和类的信息,例如类的名字、继承的基类、实现的接口等。

2、类型信息的作用:程序员可以在程序运行时发现和使用类型信息。

3、RTTI真正含义:运行时,识别一个对象的类型。

4、如何在程序运行时识别对象和类的信息?

1)传统RTTI:即在编译时已知道了所有的类型。

2)反射机制:在程序运行时发现和使用类的信息。

5、RTTI的使用

import java.util.*;      //List支持泛型

//import java.awt.List;  不支持泛型

import java.util.Arrays;

abstract class Shapes{

void draw() {System.out.println(this + ".draw()");}

abstract public String toString();

}

class Circle extends Shapes{

public String toString() {return "Circle";}

}

class Triangle extends Shapes{

public String toString() {return "Triangle";}

}

class Square extends Shapes{

public String toString() {return "Square";}

}

class Test{

public static List<Shapes> getList(){

List<Shapes> list_aShapes = Arrays.asList(new Circle() , new Square(), new Triangle());

return list_aShapes;

}

}

public class Shape {

public static void main(String[] args) {

List<Shapes> list_aShapes = Test.getList();

for(Shapes ob_aShapes : list_aShapes) {

ob_aShapes.draw();

}

}

}

运行结果:Circle.draw()

Square.draw()

Triangle.draw()

结果分析:(1)toString()都继承Object类的toSting(),派生类的toString()都会覆盖基类的该方法。

(2)Shapes.draw()中的this间接调用toString()。

(3)假设Test类是服务器端提供给客户端使用的一个类,客户端调用该类的方法(这里main()调用)获得一个泛化引用,显然,客户端并不知道泛化引用中的确切类型,而程序员需要使用到某一个确切类型对象,这时,我们就需要到RTTI。在上面的例子中,我们只是打印出泛化引用的所有类型。

二、Class对象

Class对象概述

(1)持有RTTI信息

(2)每个类都有一个Class对象,每当编译一个新类就产生一个Class对象。

(3) Class引用总是指向某个Class对象。Class引用表示的就是它所指向的对象的确切类型,而该对象便是Class类的一个对象。

()

forName()

(1)    获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类.

(2)    为了产生Class引用,forName()立即就进行了初始化。

Object-getClass()

获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。

getName()

获取全限定的类名(包括包名),即类的完整名字。

getSimpleName()

获取类名(不包括包名)

getCanonicalName()

获取全限定的类名(包括包名)

isInterface()

判断Class对象是否是表示一个接口

getInterface()

返回Class对象,表示Class对象所引用的类所实现的所有接口。

getSupercalss()

返回Class对象,表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。

newInstance()

返回一个Oject对象,是实现“虚拟构造器”的一种途径。

“虚拟构造器”:我不知道你的确切的类型,但无论如何都要正确创建你自己。

使用该方法创建的类,必须带有默认的构造器。

cast()

接受一个对象为参数,并将其转型为Class引用的类型。该法一般是在无法使用普通转型的情况下使用。

getClassLoader()

返回该类的类加载器。

getComponentType()

返回表示数组组件类型的Class。

isArray()

判定此 Class 对象是否表示一个数组类。

类字面常量

(1)一种用来生成对Class对象引用的方法。

(2)相对forName()而言,效率更高,而且不会立即引发初始化。

(3)方法:className.class;。

(4)既可用于普通类,也可用于接口、数组、基本数据类型。

…………等价于…………

boolean.class

Boolean.class

char.class

Char.class

byte.class

Byte.class

short.class

Short.class

int.class

Integer.class

long.class

Long.class

float.class

Float.class

double.class

Double.class

void.class

Void.class

泛化的Class引用

(1)实现方法:使用通配符“?”。

(2)Class<?>优于Class,即便他们是等价的。

(3)Class<?>的好处是明确地告诉编译器你选择了非具体的类版本,而不是由于碰巧或者疏忽而使用了一个非具体的类引用。

(4)创建一个范围:创建一个Class引用 ,使它被限定为某种类型<className>;或该类型的任何子类型,< ? extends superClass>;或者该类型的超类,< ? super super sunClassName>

import java.lang.Class;

import java.lang.reflect.Constructor;

interface Iterface1{}

interface Iterface2{}

abstract class SuperClass{

SuperClass(){};

SuperClass(int i){}

static {System.out.println("creating SuperClass");}

}

class SunClass extends SuperClass implements  Iterface1, Iterface2{

SunClass(){super(1);}

static {System.out.println("creating SunClass");}

}

class SunClass1 extends SuperClass implements  Iterface1, Iterface2{

SunClass1(){super(1);}

static {System.out.println("creating SunClass1");}

}

public class ClassObject {

static void printInfo(Class cc) {

System.out.println("Class name:" + cc.getName()

+ "      is Interface : " + cc.isInterface()

+"       Simple name : " + cc.getSimpleName()

+ "      Canonical name : " + cc.getCanonicalName());

}

public static void main(String[] args) {

System.out.println("/////forName()与类字面常量////////");

Class ob_aClass = null;

//对类的引用不引发初始化

Class ob_cClass = SuperClass.class;

System.out.println("After creating SuperClass");

try {

//立即初始化类

ob_aClass = Class.forName("rtti.SunClass");

System.out.println("After creating SunClass");

System.out.println("///////////////////////////////////");

}catch(ClassNotFoundException e){

System.out.println("Can't find SunClass.");

System.exit(1);

}

printInfo(ob_aClass);

System.out.println("///////Class引用实现的接口///////");

for(Class face : ob_aClass.getInterfaces())

printInfo(face);

System.out.println("//////Class引用的基类////////");

Class ob_bClass = ob_aClass.getSuperclass();

printInfo(ob_bClass);

System.out.println("///////newInstance()///////");

Object ob_aObject = null;

try {

ob_aObject = ob_aClass.newInstance();

//运行剖出异常   newInstance()该法必须由Class.forName()调用

//ob_aObject = ob_bClass.newInstance();

}catch(InstantiationException e){

System.out.println("Can't instante.");

System.exit(1);

}catch(IllegalAccessException e){

System.out.println("Can't access.");

System.exit(1);

}

printInfo(ob_aObject.getClass());

System.out.println("//////Class引用的泛型////////");

Class <? extends SuperClass>  ob_dClass = SunClass.class;

printInfo(ob_dClass);

Class <? extends SuperClass>  ob_eClass = SunClass1.class;

printInfo(ob_eClass);

//没有类型转换(Class<? super SunClass>),会出错,上位知道原因?

Class<? super SunClass>  ob_fClass = (Class<? super SunClass>)

ob_dClass.getSuperclass();

printInfo( ob_fClass);

}

}

运行结果:

creating SuperClass

creating SunClass

After creating SunClass

///////////////////////////////////

Class name:rtti.SunClass      is Interface : false       Simple name : SunClass      Canonical name : rtti.SunClass

///////Class引用实现的接口///////

Class name:rtti.Iterface1      is Interface : true       Simple name : Iterface1      Canonical name : rtti.Iterface1

Class name:rtti.Iterface2      is Interface : true       Simple name : Iterface2      Canonical name : rtti.Iterface2

//////Class引用的基类////////

Class name:rtti.SuperClass      is Interface : false       Simple name : SuperClass      Canonical name : rtti.SuperClass

///////newInstance()///////

Class name:rtti.SunClass      is Interface : false       Simple name : SunClass      Canonical name : rtti.SunClass

//////Class引用的泛型////////

Class name:rtti.SunClass      is Interface : false       Simple name : SunClass      Canonical name : rtti.SunClass

Class name:rtti.SunClass1      is Interface : false       Simple name : SunClass1      Canonical name : rtti.SunClass1

Class name:rtti.SuperClass      is Interface : false       Simple name : SuperClass      Canonical name : rtti.SuperClass

JAVA类型信息——Class对象的更多相关文章

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

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

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

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

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

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

  4. Java类型信息

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

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

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

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

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

  7. 【Java核心技术】类型信息(Class对象 反射 动态代理)

    1 Class对象 理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息.Class对象就是用来创建所有“常规”对象的,J ...

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

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

  9. Java 类型信息

    <Thinking in Java 4th>第14章 类型信息 运行时类型信息(Run-Time Type Identification)使得你可以在程序运行时发现和使用类型信息. 14. ...

随机推荐

  1. Android WIFI 启动流程(TIP^^)

    前几天因为解决一堆Bug,没时间写.我不会每天都写,就是为了存档一些资料. 内容来源:工作中接触到的+高手博客+文档(Books)=自己理解 仅限参考^^ 此博客是上一个<<Android ...

  2. 三星N8000/N8010通用刷机教程

    前面已经讲到过如何给三星n8000/n8010 Galaxy Note 10.1获取ROOT权限了.接下来就顺便告诉大家怎么给三星n8000/n8010刷机吧.其实给三星n8000/n8010刷机过程 ...

  3. 集成友盟分享SDK报错

    删除4.2.1版本的reference换成4.3版本运行报错 解决办法:要将4.2.1版本的全部库文件物理删除,不要只删除reference.

  4. 通过WebBrowser取得AJAX后的网页

    通常情况下通过WebBrowser的文档加载完成事件DocumentCompleted中进行判断 if (_WebBrowder.ReadyState == WebBrowserReadyState. ...

  5. [转]p2p端口映射工具 dog-tunnel

    [转]p2p端口映射工具 dog-tunnel http://www.oschina.net/p/dog-tunnel 狗洞是一个高速的 P2P 端口映射工具,同时支持Socks5代理. 0.5版后开 ...

  6. SDOI2016 round1滚粗记

    Day -1 刚刚从HN集训回来,感觉整个人萌萌哒.考前不断立flag——这次我一定会滚粗的,然后设想着滚粗之后文化课先补什么,浑浑噩噩的过了一天,晚上看到CA爷(娘)发了关于cena爆栈的问题,这时 ...

  7. 项目中添加Log4J支持

    首先,在项目中的classes 中新建立一个log4j.properties文件即可: 在实际编程时,要使Log4j真正在系统中运行事先还要对配置文件进行定义.定义步骤就是对Logger.Append ...

  8. JPA学习---第十节:JPA中的一对一双向关联

    1.创建实体类,代码如下: 代码清单1: package learn.jpa.entity; import javax.persistence.CascadeType; import javax.pe ...

  9. 如何在Report Builder中使用fnd_profile.value

    在EBS的Report开发中,需要根据客户化的一个Profile来控制用户可以访问的数据,可是在开发的过程中发现一直取不到该Profile的值,后来百度才找到了原因. 解决方法: 1.添加用户参数p_ ...

  10. CS小分队第一阶段冲刺站立会议(5月8日)

    昨日成果:优化了扫雷游戏,解决了界面随格子数改变却不能缩小的bug,另外改写了程序,能使用户在点下第一个雷时再生成代码,防止第一步踩到地雷. 遇到的困难:主要就是考虑扫雷需不需要有一个存档,这个存档用 ...