美文网首页
第十四章-类型信息--Class对象

第十四章-类型信息--Class对象

作者: 落叶刻痕 | 来源:发表于2017-05-02 16:46 被阅读0次

    在Java的思想里面,万事万物皆对象:

    其中类也是对象,所有的类都是一个Class对象,可以通过 类名.class 的方式获取该类的Class对象,也可以通过使用Class类的一个静态方法forName("全限定类名");的方式获取该类的Class对象,其中forName()方法当类名不存在的时候会抛出一个ClassNotFoundException异常,有趣的一点是,使用 类名.class 的方法类不会初始化,使用forName()方法 类会初始化。Class类的一些方法:
    1.getName()和getCanonicalName()方法都会返回一个全限定类名(包含包名)
    2.getSimpleName()该方法返回一个不包含包名的类名
    3.getInterfaces()返回该类实现的所有的接口
    4.isInterface()该类为接口时返回true,否则返回false;
    5.getSuperclass();返回该类的直接父类的Class对象
    6.newInstance();该方法能够在没有任何类型信息的情况下创建一个该类的实例,并返回一个Object对象,当然,在你可以发送Object能够接受的消息之外的任何消息之前,你更多的了解它并执行某种转型,该方法是实现虚拟构造器的一种途径,虚拟构造器允许你申明:“我不知道你的具体类型,但是无论如何你要正确的创建自己”。示例如下:

    interface Run{}
    interface Eat{}
    interface Sleep{}
    
    class People{
        public int a = 10;
    
        People(){}
    
        People(int i){}
    
        @Override
        public String toString() {
            return "this is a class People toString!";
        }
    }
    
    class Man extends People implements Run,Eat,Sleep{
        Man(){
            super(1);
        }
    }
    public class ClassTest {
        public static void main(String[] args){
            Class c = Class.forName("com.cuit.typeinfo.Man");
            Class up = c.getSuperclass();
            People people = null;
            try {
                people = (People) up.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            System.out.println(people.a);
            Object obj = null;
            try {
                obj = up.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            System.out.println(obj.toString());
    
        }
    }
    

    在上例中我们并没有up的任何更进一步的类型信息,只知道他是一个Class引用,但我们利用newInstance()方法成功的获得了该类的实例,并在知道了他是People类的时候将其转型为People对象。


    类字面常量:

    为了使用类而做的准备工作实际包含三个步骤:
    1.加载:由类加载器执行,创建一个Class对象
    2.链接:为静态域分配存储空间,如果必须将解析这个类创建的对其他类的所有引用
    3.初始化:如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块
    关于初始化有以下几点:
    1.初始化被延迟到了对静态方法(构造器隐式的是静态的)或者非常数静态域进行首次引用时才执行
    2.关于 static 和 final 关键字:如果一个值是编译期 常量并被声明为static final那么这个值不需要初始化便能读取,如果一个static域不是final的,那么对它访问时必须要先进行连接(为这个域分配存储空间)和初始化(初始化该存储空间)


    泛型与Class:

    当将泛型语法用于Class对象时,会发生一件有趣的事情:newInstance()方法会返回该对象的确切类型而不是基本的Object,但如果你手头是超类,则有一些不同,如下:

    //Class<? super Man> 方式获得的Class对象在调用newInstance()方法时返回的是Object而不是Man的超类People
            Class<People> c = People.class;
            Class<? super Man> upp = c.getSuperclass();
            try {
                Object o = upp.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
     //当手头的是People的子类Man时,使用newInstance()方法返回People
            Class<? extends People> tClass = Man.class;
            try {
                People people1 = tClass.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    

    类型转换:

    当尝试向上转型时,编译器允许自由的做向上转型的赋值操作,二不需要做任何显示的转型操作
    向下转型:
    向下转型时,编译器将检查向下转型是否合理,因为他不允许向下转型到实际上不是待转型类的子类的类型上,可以使用关键字instanceof,它返回一个布尔值,告诉我们对象是否是某个特定类的实例

    if(x instanceof Man){
        //do something...
    }
    

    动态的instanceof: isInstance(T);

    相关文章

      网友评论

          本文标题:第十四章-类型信息--Class对象

          本文链接:https://www.haomeiwen.com/subject/ruoctxtx.html