java类型信息

java类型信息是运行时也可以获得,不像c++在编译时确定。运行时类型信息可以让你在程序运行时发现和使用类型信息。

java有两种方法让你获得运行时信息:“传统的”RTTI(runtime type information),它假定在编译时就已经知道了全部信息;反射,让你能够在运行时发现信息。仅仅知道这些还不好区分RTTI和反射的区别,下面来看一段java编程思想上的一句原话:

So the true difference between RTTI and reflection is that with RTTI, the compiler opens and examines the .class file at compile time. Put another way, you can call all the methods of an object in the "normal" way. With reflection, the .class file is unavailable at compile time; it is opened and examined by the runtime environment.

RTTI编译的时候已经打开和检查过了.class文件,所以可以“正常的”、“直接的”调用类的方法。比如下面的类:

public class A{
    void method1(){}
    public void method2(){}
}

然后可以在其他包中直接建立一个对象A a=new A(),然后调用他的方法,a.method2(),但是a.method1()会报错,因为不在同一包中不能访问。正是因为编译器在阶段就检查了类A,因此你不会存在编译的错误,比如调用没有权限调用的函数method2。

而反射没有在编译时检查类,而是在运行时检查类。前面我们说过,RTTI在编译时就知道了全部的类信息,因此建一个类A的对象a,可以直接使用a.method2()调用方法,而如果编译器时并不知道类A呢?(当从网络上下载.class文件时,编译器会不知道该类信息)而是在运行时通过Class<?> class=Class.forName("packageName.A");来得到Class对象。然后使用Object object=class.newInstance();来得到对象,此时因为编译时不知道A的信息,因此只能赋值给Object。那如何调用他的方法呢?当然通过Class对象来获得关于方法的类(java.lang.reflect.Method)的对象,通过该对象调用函数,在这个过程中需要处理异常,这就相当于在运行时检查类了。

这是我对java编程思想的理解,但是我也认为就是编译时知道了全部信息也可以使用放射,毕竟都是对Class对象操作,,,而反射不过是通过java.lang.reflect包中的类来获得类信息罢了。

Class对象

想了解类型信息在运行时如何被表示,必须要知道Class对象。每一个类型对应一个Class对象,该对象含有关于该类的信息。Class对象在被需要的时候通过类加载器加载。jvm的类加载器子系统由一串(a chain of)的类加载器实现,只有最顶端的类加载器由jvm实现,只加载java api。

类只会在被使用的时候加载且仅加载一次,所谓使用就是指当类的静态成员的引用被使用。类的构造函数可以看成是静态的(尽管没有使用static声明),因此在使用new实例化对象时,调用了构造函数,因此如果类没有被加载则加载。注意,使用类的常静态成员且初始值可以编译时确定(final static)不会造成类的加载。

一般的情况下,类被加载时会被初始化。

类字面值

除了可以使用Class.forName()在动态时获得该类的Class对象,还可以使用类字面值在编译时获得类的Class对象。因为类字面值在编译时需要接收检查,因此不需要像Class.forName()那样要放在try语句块中检查。

类字面量可以获得编译时已知的所有类的Class对象,包括基本类型。下面的表给出了获得基本类型Class对象的方法,通过TYPE也可以从包装类获得基本类的Class对象。

需要注意的是,但使用类字面量获得Class对象时,类不会被初始化。只有静态方法或者非常数静态域(初始值编译时确定)则初始化,和类加载差不多。。

通常为了使类可用,需要做以下三个步骤:

  1. Loading, which is performed by the class loader. This finds the bytecodes (usually, but not necessarily, on your disk in your classpath) and creates a Class object from those bytecodes.
  2. Linking. The link phase verifies the bytecodes in the class, allocates storage for static fields, and if necessary, resolves all references to other classes made by this class.
  3. Initialization. If there’s a superclass, initialize that. Execute static initializers and static initialization blocks.

也就是加载、链接、初始化。

获得Class对象的方法

1、如果有对象object,可以直接通过调用类Object的getClass方法获得该对象的Class对象:

object.getClass();

2、直接通过Class的静态方法forName()获得Class对象,这种方法不需要使用类的对象。

3、第三种就是通过上面的类字面值常量。比如类A,通过A.class获得该类的Class对象。

4、直接通过类加载器ClassLoader的loadClass方法获得。

。。。。有点乱

参考:

thinking in java 4th edition java编程思想

https://www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值