• java 类型信息


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

    一.为什么需要RTTI(Run-Time Type Information)

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

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

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

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

    二.Class对象

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

    1. 每个类都有Class对象,即编译了一个新类就会产生一个该类的Class对象,并且保存在.class文件中。Class对象就是用来产生“常规”对象的。
    2. Java使用Class对象来执行RTTI。
    3. 所有类都是第一次使用时动态加载到jvm中。 动态加载就是需要时再加载不使用不加载。
    4. 只要创建了对一个类的静态成员的引用就会加载该类。new 的时候加载类说明 类的构造器虽然没写static但也是静态方法。

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

    package test;
    
    class Candy {
    static { System.out.println("Loading Candy"); }
    }
    
    class Gum {
    static { System.out.println("Loading Gum"); }
    }
    
    class Cookie {
    static { System.out.println("Loading Cookie"); }
    }
    
    public class SweetShop {
    public static void main(String[] args) {    
     System.out.println("inside main");
     new Candy();
     System.out.println("After creating Candy");
     try {
       Class.forName("Gum");//返回的是一个Class对象的引用如果获取失败会抛出异常 ClassNotFoundException
     } catch(ClassNotFoundException e) {
       System.out.println("Couldn't find Gum");
     }
     System.out.println("After Class.forName("Gum")");
     new Cookie();
     System.out.println("After creating Cookie");
    }
    } /* Output:
    inside main
    Loading Candy
    After creating Candy
    Loading Gum
    After Class.forName("Gum")
    Loading Cookie
    After creating Cookie
    *///:~
    /* 注意新版本jdk和作者的结果不一样
     * inside main
    Loading Candy
    After creating Candy
    Couldn't find Gum
    After Class.forName("Gum")
    Loading Cookie
    After creating Cookie
    *///~
     */

    运行时要获得一个类的信息(类型信息)可以通过一个该类的Class对象获得,使用Class.forName()就可以做到,而不必持有该类型的对象通过该对象获得。

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

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

    1. getName() 获得全限定类名, getCanonicalName()也是获得全限定类名。对于普通类来说,二者没什么区别,只是对于特殊的类型上有点表示差异。
    2. getSimpleName()只获得类名,没有包名。
    3. isInterface()判断是否为接口。
    4. getInterfaces() 返回一个Class对象数组,数组元素是该类实现的接口,元素顺序和实现顺序一致。
    5. getSuperclass() 返回直接基类(不是接口)的Class对象,可以用来发现对象完整的类继续结构。
    6. newInstance()创建该类实例对象并返回,但该类必须要有默认构造器,这个方法相当于一个虚拟构造器。
    //: typeinfo/toys/ToyTest.java
    // Testing class Class.
    package test;
    
    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) {
        System.out.println("Class name: " + cc.getName() +
          " is interface? [" + cc.isInterface() + "]");
        System.out.println("Simple name: " + cc.getSimpleName());
        System.out.println("Canonical name : " + cc.getCanonicalName());
      }
      public static void main(String[] args) {
        Class c = null;
        try {
          c = Class.forName("test.FancyToy");
        } catch(ClassNotFoundException e) {
          System.out.println("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) {
          System.out.println("Cannot instantiate");
          System.exit(1);
        } catch(IllegalAccessException e) {
          System.out.println("Cannot access");
          System.exit(1);
        }
        printInfo(obj.getClass());
      }
    } /* Output:
    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
    Class name: typeinfo.toys.Toy is interface? [false]
    Simple name: Toy
    Canonical name : typeinfo.toys.Toy
    *///:~
  • 相关阅读:
    String 总结
    android 调试源码
    Java 随机数总结
    Android中如何控制调节屏幕亮度
    Activity中通过Bundle传递自定义数据类型
    Android AsyncTask简单用法
    WCF 第五章 可信赖会话
    WCF 第五章 会话级别的实例
    WCF 第五章 行为 在WCF一个服务内部的事务操作
    WCF 第五章 导出并发布元数据(服务行为)
  • 原文地址:https://www.cnblogs.com/jiangfeilong/p/10347216.html
Copyright © 2020-2023  润新知