• Thinking in java Chapter14类型信息


    本章主要学习如何让我么在运行时识别对象和类的信息的.主要有两种方式:一种是传统的RTTI它假定我们在编译时已经知道了所有的类型. 另一种是反射机制它允许我们在运行时发现和使用类的信息.

    1 为什么需要RTTI

    1. RTTI :在运行时识别一个对象的类型

    2.反射 允许在运行时发现和使用类型信息

    3.传统的RTTI 在编译期通过Class文件识别类型信息,反射在运行期通过Class文件识别类型信息。

    4.Java类型转换都发生在运行时期。

    2 Class对象

    Class对象是用来创建类的所有的"常规"对象的.java使用Class对象来执行其RTTI,即使你正在执行的是转型这样的操作.

    Java使用Class对象来执行RTTI。

    每个类都有Class对象,即编译了一个新类就会产生一个该类的Class对象,并且保存在.class文件中。Class对象就是用来产生“常规”对象的。

    类加载器

    所有类都是第一次使用时动态加载到jvm中。

    动态加载就是需要时再加载不使用不加载。

    只要创建了对一个类的静态成员的引用就会加载该类。new 的时候加载类说明

    类的构造器虽然没写static但也是静态方法。因此,使用new操作符创建类的新对象也会被当作对类对静态成员对引用

    一旦某个类的Class对象载入内存后,他就会用来创建该类的对象。

    运行时要获得一个类的信息(类型信息)可以通过一个该类的Class对象获得,使用Class.forName()就可以做到,而不必持有该类型的对象通过该对象获得。
    
    package typeinfo;
    
    import static net.mindview.util.Print.print;
    
    class Candy {
        static {
            print("Loading Candy");
        }
    }
    
    class Gum { // 口香糖
        static {
            print("Loading Gum");
        }
    }
    
    class Cookie {
        static {
            print("Loading Cookie");
        }
    }
    
    public class SweetShop {
        public static void main(String[] args) {
            print("inside main");
            new Candy();
            print("After creating Candy");
            try {
                Class.forName("typeinfo.Gum"); // 与书有区别  typeinfo.Gum 全限定名  // 返回的是一个Class对象的引用
                Class.forName("Gum"); // 如果获取失败会抛出异常 ClassNotFoundException
            } catch (ClassNotFoundException e) {
                print("Couldn't find Gum");
            }
            print("After Class.forName("Gum")");
            new Cookie();
            print("After creating Cookie");
        }
    }
    /* 
    inside main
    Loading Candy
    After creating Candy
    Couldn't find Gum
    After Class.forName("Gum")
    Loading Cookie
    After creating Cookie
     */
    
    

    如果有了一个实例对象可以调用getClass()方法来获得Class对象, 这个方法属于根类Object的一部分

    Class包含很多有用的方法,下面是其中的一部分

    getName() 获得全限定类名, getCanonicalName()也是获得全限定类名。对于普通类来说,二者没什么区别,只是对于特殊的类型上有点表示差异。
    getSimpleName()只获得类名,没有包名。
    isInterface()判断是否为接口。
    getInterfaces() 返回一个Class对象数组,数组元素是该类实现的接口,元素顺序和实现顺序一致。
    getSuperclass() 返回直接基类(不是接口)的Class对象,可以用来发现对象完整的类继续结构。
    newInstance()创建该类实例对象并返回,但该类必须要有默认构造器,这个方法相当于一个虚拟构造器。

    package typeinfo.toys;
    
    import static net.mindview.util.Print.print;
    
    interface HasBatteries{}
    interface Waterproof{}
    interface Shoots{}
    
    class Toy{
        // Comment out the following default constructor
        // to see NoSuchMethodError from (*1*)
    //    Toy(){}
        Toy(int i){}
    }
    
    class FancyToy extends Toy implements HasBatteries,Waterproof,Shoots{
        FancyToy(){
            super(1);
        }
    }
    
    public class ToyTest {
        static void printInfo(Class cc){
            print("Class name: " + cc.getName() +
                    " is interface ? [" + cc.isInterface() +"]");
            print("Simple name: " + cc.getSimpleName());
            print("Canonical name: " + cc.getCanonicalName());
        }
    
        public static void main(String[] args) {
            Class c = null;
            try{
                c = Class.forName("typeinfo.toys.FancyToy");
            }catch (ClassNotFoundException e){
                print("Can't find FancyToy");
                System.exit(1);
            }
    
            printInfo(c);
    
            for (Class face:c.getInterfaces())
                printInfo(face);
    
            Class up = c.getSuperclass();
            Object obj = null;
            try{
                // Requires default constructor:
                obj = up.newInstance();
            }catch (InstantiationException e){
                print("Cannot instantiate");
                System.exit(1);
            }catch (IllegalAccessException e){
                print("Cannot access");
                System.exit(1);
            }
            printInfo(obj.getClass());
        }
    }
    /*
    Class name: typeinfo.toys.FancyToy is interface ? [false]
    Simple name: FancyToy
    Canonical name: typeinfo.toys.FancyToy
    Class name: typeinfo.toys.HasBatteries is interface ? [true]
    Simple name: HasBatteries
    Canonical name: typeinfo.toys.HasBatteries
    Class name: typeinfo.toys.Waterproof is interface ? [true]
    Simple name: Waterproof
    Canonical name: typeinfo.toys.Waterproof
    Class name: typeinfo.toys.Shoots is interface ? [true]
    Simple name: Shoots
    Canonical name: typeinfo.toys.Shoots
    Cannot instantiate
     */
    
    
    
  • 相关阅读:
    JavaScript 事件对象Event的工具类
    高度组件专一性的松耦合系统CI的MVC
    [转]解决PHP相对目录问题最有效的办法
    CodeIgniter 用户登录注册模块
    记录js的四种函数写法
    Firebug 控制台API
    jQuery实战(一)
    apache:一个ip绑定多个域名的问题(续)
    JavaScript 字符串操作(一)
    hdu 1166 敌兵布阵【树状数组入门】
  • 原文地址:https://www.cnblogs.com/erinchen/p/11910174.html
Copyright © 2020-2023  润新知