java类型信息_Java类型信息rtti

RTTI Run-Time Type Infomation(运行时类型信息),在Java运行时,RTTI维护类的相关信息,识别类和对象的信息。

多态(polymorphism)是基于RTTI实现的。RTTI的功能主要是由Class类实现的。

严格的说,反射也是一种形式的RTTI,不过,一般的文档资料中把RTTI和反射分开,因为一般的,大家认为RTTI指的是传统的RTTI

,通过继承和多态来实现,在运行时通过调用超类的方法来实现具体的功能(超类会自动实例化为子类,或使用instance of)。

传统的RTTI有3种实现方式:

1.向上转型或向下转型(upcasting and downcasting),在java中,向下转型(父类转成子类)需要强制类型转换。

2.Class对象(用了Class对象,不代表就是反射,如果只是用Class对象cast成指定的类,那就还是传统的RTTI)。

3.instanceof或isInstance()。

其中cast的用法如下所示:

public class Test1 {

public static void main(String[] args) throws ClassNotFoundException {

Father f = new Child();

Class cc = Child.class ;

Child c = cc.cast(f) ;

}

}

class Father {

}

class Child extends Father {

}

这里 Child c = cc.cast(f) ; 等价于 Child c = (Child)f ;

传统的RTTI与反射最主要的区别:RTTI,编译器在编译时打开和检查.class文件。

而反射不需要,反射在运行时打开和检查.class文件。传统的RTTI使用转型或Instance形式实现,

但都需要指定要转型的类型,比如:

public void rtti(Object obj){

Toy toy = Toy(obj);

// Toy toy = Class.forName("com.rtti.Toy")

// obj instanceof Toy

}

注意其中的obj虽然是被转型了,但在编译期,就需要知道要转成的类型Toy,也就是需要Toy的.class文件。

相对的,反射完全在运行时在通过Class类来确定类型,不需要提前加载Toy的.class文件。

Class类

Class类是”类的类”(class of classes)。如果说类是对象的抽象和集合的话,那么Class类就是对类的抽象和集合。

每一个Class类的对象代表一个其他的类。比如下面的程序中,Class类的对象c1代表了Father类,c2代表了Child类。

public class Test1 {

public static void main(String[] args)

{

Father father = new Father();

Class c1 = father.getClass();

System.out.println(c1.getName());

Father child = new Child();

Class c2 = child.getClass();

System.out.println(c2.getName());

}

}

class Father {

}

class Child extends Father {

}

当我们调用对象的getClass()方法时,就得到对应Class对象的引用。

在c2中,即使我们将child对象的引用向上转换为Father对象的引用,对象所指向的Class类对象依然是Child。

Java中每个对象都有相应的Class类对象,因此,我们随时能通过Class对象知道某个对象“真正”所属的类。无论我们对引用进行怎样的类型转换,

对象本身所对应的Class对象都是同一个。当我们通过某个引用调用方法时,Java总能找到正确的Class类中所定义的方法,并执行该Class类中的代码。

由于Class对象的存在,Java不会因为类型的向上转换而迷失。这就是多态的原理。

除了getClass()方法外,我们还有其他方式调用Class类的对象。

public class Test1 {

public static void main(String[] args) throws ClassNotFoundException {

Class c1 = Class.forName("com.souly.myapplication.test.Father");

System.out.println(c1.getName());

Class c2 = Child.class ;

System.out.println(c2.getName());

}

}

class Father {

}

class Child extends Father {

}

上面显示了两种方式:

1.forName()方法接收一个字符串作为参数,该字符串是类的名字。这将返回相应的Class类对象。

2.Child.class方法是直接调用类的class成员。这将返回相应的Class类对象。

使用forName(String str)有一个副作用:如果类没有被加载,调用它会触发类的static子句(静态初始化块)。与之相比,更好用的是类字面常量,

例如Child.class。支持编译时检查,所以不会抛出异常。使用类字面常量创建Class对象的引用与forName(String str)

不同,不会触发类的static子句(静态初始化块)。所以,更简单更安全更高效。类字面常量支持类、接口、数组、基本数据类型。

Class类的加载

Java程序在运行之前并没有被完全加载,各个部分是在需要时才被加载的。

为了使用类而作的准备包含三步:

1.加载。由classloader查找class字节码文件,创建一个Class对象。

2.链接:验证字节码文件,为静态域分配存储空间,如果必需的话,会解析这个类创建的对其他类的所有引用(比如说该类持有static域)。

3.初始化:初始化父类,执行静态初始化器和静态初始化块。

其中静态初始化器可以理解为静态域在定义处的初始化,如:static Dog d = new Dog(0);。

final static成员和static成员的在以上三个过程中不一样,final static成员被称为“编译器常量”,在编译时已经被赋值,

所以可以在类加载前就进行访问,而静态成员(非final)需要在类加载后、class对象初始化之后赋值。

当Java创建某个类的对象,jvm虚拟机的classLoader会检测对象对应的Class对象是否已加载,

比如Child类对象时,Java会检查内存中是否有相应的Class对象。如果内存中没有相应的Class对象,会依据相关途径查询对应.class文件

(如 通过classPath在本地文件系统进行查找,在获取到.class文件之后会对文件进行有效验证,之后会依据Class对象进行详细类型对象的创建。

在Class对象加载成功后,其他Child对象的创建和相关操作都将参照该Class对象。

更详细的介绍可以参考:

举例说明

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() + "]");

}

public static void main(String[] args) {

Class c = null;

try {

c = Class.forName("com.souly.myapplication.test.FancyToy");

} catch(ClassNotFoundException e) {

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

System.exit(1);

}

printInfo(c);

Class[] faces = c.getInterfaces();

for(int i = 0; i < faces.length; i++)

printInfo(faces[i]);

Class cy = c.getSuperclass();

Object o = null;

try {

// Requires default constructor:

o = cy.newInstance(); // (*1*)

} catch(InstantiationException e) {

System.out.println("Cannot instantiate");

System.exit(1);

} catch(IllegalAccessException e) {

System.out.println("Cannot access");

System.exit(1);

}

printInfo(o.getClass());

}

}

运行后输出结果如下:

Class name: com.souly.myapplication.test.FancyToy is interface? [false]

Class name: com.souly.myapplication.test.HasBatteries is interface? [true]

Class name: com.souly.myapplication.test.Waterproof is interface? [true]

Class name: com.souly.myapplication.test.Shoots is interface? [true]

Class name: com.souly.myapplication.test.Toy is interface? [false]

从中可以看出,class FancyToy相当复杂,因为它从Toy中继承,并实现了HasBatteries,Waterproof以及ShootsThings的接口。在main()方法中

有一个Class对象,它通过Class.forName()初始化成FancyToy Class。Class.getInterfaces方法会返回Class对象的一个数组,用于表示Class对象内的接口。

若有一个Class对象,也可以用getSuperclass()查询该对象的直接父类是什么。当然,这种做会返回一个Class对象,可用它作进一步的查询。

这意味着在运行期的时候,完全有机会调查到对象的完整层次结构。

若从表面看,Class的newInstance()方法似乎是克隆(clone())一个对象的另一种手段。但两者是有区别的。利用newInstance(),

我们可在没有现成对象供“克隆”的情况下新建一个对象。就像上面的程序演示的那样,当时没有Toy对象,只有cy——即Toy的Class对象。

利用它可以实现“虚拟构建器”。在上述例子中,cy只是一个Class对象,编译期间并不知道进一步的类型信息。一旦新建了一个实例后,

可以得到Object对象。但那是一个Toy对象。

用newInstance()创建的类必须有一个无参数的构造方法。没有办法用newInstance()创建拥有非默认构建方法的对象,如果我们注释掉Toy() {}构造方法,

将会报错:java.lang.InstantiationException。

参考阅读:

基于SSM框架的智能家政保洁预约系统,是一个旨在提高家政保洁服务预约效率和管理水平的平台。该系统通过集成现代信息技术,为家政公司、家政服务人员和消费者提供了一个便捷的在线预约和管理系统。 系统的主要功能包括: 1. **用户管理**:允许消费者注册、登录,并管理他们的个人资料和预约历史。 2. **家政人员管理**:家政服务人员可以注册并更新自己的个人信息、服务类别和服务时间。 3. **服务预约**:消费者可以浏览不同的家政服务选项,选择合适的服务人员,并在线预约服务。 4. **订单管理**:系统支持订单的创建、跟踪和管理,包括订单的确认、完成和评价。 5. **评价系统**:消费者可以在家政服务完成后对服务进行评价,帮助提高服务质量和透明度。 6. **后台管理**:管理员可以管理用户、家政人员信息、服务类别、预约订单以及处理用户反馈。 系统采用Java语言开发,使用MySQL数据库进行数据存储,通过B/S架构实现用户与服务的在线交互。系统设计考虑了不同用户角色的需求,包括管理员、家政服务人员和普通用户,每个角色都有相应的权限和功能。此外,系统还采用了软件组件化、精化体系结构、分离逻辑和数据等方法,以便于未来的系统升级和维护。 智能家政保洁预约系统通过提供一个集中的平台,不仅方便了消费者的预约和管理,也为家政服务人员提供了一个展示和推广自己服务的机会。同时,系统的后台管理功能为家政公司提供了强大的数据支持和决策辅助,有助于提高服务质量和管理效率。该系统的设计与实现,标志着家政保洁服务向现代化和网络化的转型,为管理决策和控制提供保障,是行业发展中的重要里程碑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值