看Java编程思想,头晕,写下点自己的理解
1 首先,参考文献
- Java编程思想,14.2章节
- https://www.cnblogs.com/vamei/archive/2013/04/14/3013985.html (作者:Vamei )引用了这位博主的部分代码
- 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 和类字面常量的区别
- Class.forName() 方法返回Class对象的引用,其作用是如果该类没有被加载到JVM中,就将其加载,static初始化就是在类加载的时候执行的,执行后会自动执行类的初始化。
- “xx.class”创建Class对象引用,执行后不会执行类的初始化(初始化被延迟到了对静态域的首次访问)
- “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
这样有时候可能引起混淆吧~~