【Java Class对象】RTTI 和Class对象

8 篇文章 0 订阅

看Java编程思想,头晕,写下点自己的理解

1 首先,参考文献

  1. Java编程思想,14.2章节
  2. https://www.cnblogs.com/vamei/archive/2013/04/14/3013985.html (作者:Vamei )引用了这位博主的部分代码
  3. http://www.matools.com/api/java8 Java8API

2 RTTI是什么?

RTTI, Run-Time Type Identification,运行时类型信息。这个东西可以使你在程序运行时发现和使用类型信息(类名,类所在包,类方法…)

3 RTTI咋实现的?–Class对象

引用Vamei博主文章中的一句话,个人觉得很有道理。

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

这里听起来是有点绕哈,我们常说,Java里面“万物皆是类”,所有的东西都可以用类表示,这是面向对象中“抽象”的概念。那么再用一个东西去描述一下所有的类,这就是Class类(这里的Class类可以换一个词描述,比如XXX类,这个类专门用来描述类的信息)

再举个例子,在理解类对象之前,先说我们熟悉的对象之间的区别:
小敏和小娴都是Human对象,她们的区别在于,各自有不同的名字,性别,爱好
然后说说类之间的区别
Human和Animal都是类,它们的区别在于有不同的方法,不同的属性。

类对象( Class 对象),就是用于描述这种类,都有什么属性,什么方法的
----How2Java

4 Class对象实现的3种方法

4.1 通过一个已经存在的对象,调用.getClass()方法
4.2 Class.forName(“类全限定名”)
4.3 类字面常量 “xx.class”

举个例子,上代码

public class TestDemo
{
    public static void main(String[] args) throws ClassNotFoundException {
        Human aPerson = new Human();
        Class c1      = aPerson.getClass();
        System.out.println(c1.getName());

        Class c2      = Class.forName("Human");
        System.out.println(c2.getName());

        Class c3      = Woman.class;
        System.out.println(c3.getName());
    }
}

class Human
{
    /**
     * accessor
     */
    public int getHeight()
    {
        return this.height;
    }

    /**
     * mutator
     */
    public void growHeight(int h)
    {
        this.height = this.height + h;
    }
    private int height;
}


class Woman extends Human
{
    /**
     * new method
     */
    public Human giveBirth()
    {
        System.out.println("Give birth");
        return (new Human());
    }

}

结果:
在这里插入图片描述

5 Class.forName 和类字面常量的区别

  1. Class.forName() 方法返回Class对象的引用,其作用是如果该类没有被加载到JVM中,就将其加载,static初始化就是在类加载的时候执行的,执行后会自动执行类的初始化
  2. “xx.class”创建Class对象引用,执行后不会执行类的初始化(初始化被延迟到了对静态域的首次访问)
  3. “xx.class”更安全,因为它在编译时候就会受到检察。forName()是运行时检查的,所有一般要套在try-catch语句中。
所有的类都是在对其第一次使用时,动态加载到JVM中的,当程序创建第一个对类的静态成员引用时候,就会加载这个类。(new 操作符也会被当做对类静态成员的引用)

6 Java中多态的本质

举个多态的例子,animal是父类,有一个sing方法。cat是子类,继承于animal,并且重写了sing方法。如下例子

  class Animal{
        public void sing(){
            System.out.println("animal sing");
        }
    }

    class Cat extends Animal{
        public void sing(){
            System.out.println("cat sing");
        }
    }

当我们使用animal类指向一个cat对象,然后通过animal 去调用sing() 方法时,就像下面这样

Animal animal = new Cat();
animal.sing()

实际的输出应该是

cat sing

这是一个很简单的多态的例子。那么JVM是如何知道,anima实际指向的是一个cat对象的?答案就是RTTI。也就是刚刚说的class对象。不管cat向上转型多少次,它的class对象(getClass)永远是是cat类。所以,我们调用sing() 方法的时候,JVM会去调用Cat的sing()方法。这就是多态的原理。

7 Class对象常用的API

在这里插入图片描述

getFields()       //返回所有的public数据成员

getMethods()      //返回所有的public方法

getName()         //返回类的名字

getPackage()      //返回类所在的包

newInstance()     //创建由此 类对象表示的类的新实例。

getSuperclass()   // 返回父类的class对象

特别想说明下**newInstance()**这个函数,它在官方文档上的说明是,
在这里插入图片描述
如果初始化时候,没有使用泛型的话,是会报错的。
在这里插入图片描述
加上泛型之后就可以正常使用了
在这里插入图片描述

关于为什么一般都要要加上泛型,官方的说法是,如果不指定泛型的话,那么一个class引用可以多次指向不同的Class对象(也就是说可以指向Human可以指向Woman),like this
在这里插入图片描述
这样有时候可能引起混淆吧~~

8 Ending 新手上路,如有谬误,欢迎指出~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值