• Thinking in Java -- 类型信息RTTI


    Thinking in Java – 类型信息

    个人感觉 java 中的比較难的部分了,在看了些netty源代码发现事实上这块很实用。


    这章重点是RTTI和反射。先说下自己的理解
    RTTI是执行时识别。在c++中是用virtual来实现的,在编译期会忽略对象的详细类型信息,假定我们已经知道,并在执行时详细识别。

    Java反射机制实在执行状态中,对于随意一个类,都能够知道这个类的全部属性和方法。对于随意一个对象。都能够调用它的随意一个方法和属性,这样的动态获取的信息以及动态调用对 象的方法的功能称为Java的反射机制


    Class对象

    Class对象就是用来创建类的全部的“常规”对象的。Java使用Class对象来执行其RTTI.
    Class对象是什么
    Java是一门纯面向对象的语言。在Java中,一切都是对象,也就是class,对于每一个类文件(每一个对象)编译后我们都会生成一个.class文件(javac hello.java —> hello.class)。*.class文件就是Class对象,在我们要第一次使用hello这个类文件时。JVM的类载入器会来载入hello.class文件,感觉Class对象就是一个模具。用来生产对象的。
    注意:构造器也是静态方法

    样例:

    package onefour_chapter;
    
    /**
     * Created by wwh on 15-8-7.
     */
    
    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");
            }catch (ClassNotFoundException e){
                System.out.println("not found Gum");
            }
            System.out.println("After Class.forName("Gum")");
            new Cookie();
            System.out.println("After create Cookie");
        }
    }
    

    这里写图片描写叙述
    我执行完发现结果和书上不一致,原因是Class.forName()參数要求是全然限定名,我的代码在包中。前面加上包名字就可以,例如以下
    Class.forName(“包名.Gum”);

    关键点:

    static代码块

    static修饰的代码块仅仅在类被载入时执行而且仅会被执行一次。一般用来初始化静态变量和调用静态方法,无论你new多少次,在jvm的声明周期里一个类仅仅被载入一次。
    前面说构造器也是静态方法,所以test t = new test(),在第一次创建对象时jvm就会载入test类的Class对象(.class文件),Class对象就和其它对象一样,我们能够操控它的引用。forName()就是获取Class对象引用的一种方法。
    Class.forName()返回对象的Class引用,从Class对象中我们能够获得许多的信息从而在执行时来抉择一些事情。很像c++的type_traits。注意使用newInstance()创造的类必须带有默认的构造器

    static语句块
    static语句块在类载入时执行。仅仅被执行一次
    在用单例模式写封装数据库连接池时,new一个数据库连接池就被我写在了static代码块中,保证在类载入时就初始化好连接池,且仅仅初始化一次。(注意。訪问静态常量时。假设编译器能计算出来。则不会载入)

    类载入:在终端下Java载入.class文件。Java命令的作用是启动虚拟机。虚拟机通过流从磁盘上将字节码(.class文件)中的内容读入虚拟机,并保存起来的过程。


    类字面常量

    Java还提供了一种方法来生成Class对象的引用,即类字面常量,classname.class,比方hello.class。它更安全和高效也不用try语句包裹。所以一般我们不使用forName(),可用于类,接口,数组。基本类型。建议使用.class的形式。.class执行了“尽可能”懒惰初始化,而forName()马上就初始化
    为了使用类而做的准备工作有3个。载入–>连接–>初始化


    范化的Class引用

    Class引用总是指向某个Class对象,它能够制造类的实例。并包括可作用于这些实例的全部方法代码。它还包括该类的静态成员,因此,Class引用表示的就是它所指向的对象的确切类型。该对象便是Class类的一个对象。
    向Class引用加入范型语法原因仅仅是为了编译器类型检查。前面说了RTTI和反射都是执行时的。如今我们在编译时也做了一些限定。更加保证了执行的正确性
    为了在使用范化的Class引用时放松限制。能够使用了通配符,也但是使用通配符和extends关键字相结合。创建一个范围。
    Class

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by wwh on 15-8-7.
     */
    
    class CountedInteger{
        static {
            System.out.println("Class 载入");
        }
        private static long counter;
        private final long id = counter++;
        public String toString() { return Long.toString(id); }
    }
    
    public class FilledList<T> {
        private Class<T> type;
        /* 构造函数。參数为被限定的Class对象,我们能够在实例化时来指定 */
        public FilledList(Class<T> type){ this.type = type; }
        public List<T> create(int nElements){
            List<T> result = new ArrayList<T>();
            try{
                for(int i = 0; i < nElements; i++){
                    result.add(type.newInstance());
                }
            }catch (Exception e){
                throw new RuntimeException();
            }
            return result;
        }
    
        public static void main(String[] args){
            /* 执行限定的类型,并传递.class作为构造函数的參数 */
            FilledList<CountedInteger> fl = new FilledList<CountedInteger>(CountedInteger.class);
            System.out.println(fl.create(15));
        }
    
    } 

    RTTI在Java中的第三种形式是instanceof,它返回一个布尔值,告诉我们对象是不是某个特定的实例。
    if(obj instanceof Dog) obj.exe();
    instanceof有比較严格的限制,仅仅能将其与命名类型进行比較。而不能与FClass对象作比較
    Class.isInstance()方法提供了一种动态地測试对象的途径。

  • 相关阅读:
    在spring中该如何使用DTO,以及DTO和Entity的关系
    AngularJs踩过的坑
    springMVC正确使用GET POST PUT和DELETE方法,如何传递参数
    Mac下使用终端连接远程使用ssh协议的git服务器
    springMVC的异常处理
    根据业务规则分析业务对象,然后生成表结构
    在线资源--图片/json等
    js中的Hook
    diamond源码阅读-目录监控
    maven常用命令
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7162641.html
Copyright © 2020-2023  润新知