• Java 反射机制:(二)Class类


    一、Class 类

      1、Class 类概述

        在Object类中定义了以下的方法,此方法将被所有子类继承:

    public final Class getClass()
    

        

       以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

      2、java.lang.Class 类

        对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言, JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。

        ① Class本身也是一个类
        ② Class 对象只能由系统建立对象
        ③ 一个加载的类在 JVM 中只会有一个Class实例
        ④ 一个Class对象对应的是一个加载到JVM中的一个.class文件
        ⑤ 每个类的实例都会记得自己是由哪个 Class 实例所生成
        ⑥ 通过Class可以完整地得到一个类中的所有被加载的结构
        ⑦ Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的 Class 对象

      3、Class 类的常用方法

        

      4、

      5、

    二、获取 Class 类的实例(四种方法)

      Java 程序中可以通过以下四种方式获取 Class 对象:

      1、方式一:调用运行时类的属性:.class

        Demo:

    1 Class clazz1 = Person.class;
    2 System.out.println(clazz1);

        这种方式适用于编译期间已知的类型,如果某个类型编译期间是已知的,优选考虑此方法

        优点:代码更安全、效率更高、简洁

        缺点:要求编译期间这个类型就要存在

        注意:基本数据类型和 void 有只能通过该方式获取 Class对象;不能通过方式三和方式四来获得

      2、方式二:通过运行时类的对象,调用getClass()

        Demo:

    1 Person p1 = new Person();
    2 Class clazz2 = p1.getClass();
    3 System.out.println(clazz2);

        这个方法在 java.lang.Object 类型中声明的,可以获取该对象的运行时类型的 Class 对象;

        适用情况:必须先有对象,才能获取 Class 对象

        注意:同一字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的 Class 对象都是同一个。

      3、方式三:调用Class的静态方法:forName(String classPath)

        Demo:

    1 Class clazz3 = Class.forName("com.java.Person");
    2 clazz3 = Class.forName("java.lang.String");
    3 System.out.println(clazz3);

        该方法需要传入一个字符串参数,该值是某个类的全限定名(即完整的包.类型名),该方法适用于除了数组以外的任意引用数据类型;

        已知一个类的全类名,且该类在类路径下, 可通过Class类的静态方 法forName()获取,可能抛出ClassNotFoundException。

        多用于配置文件,将类名定义在配置文件中,读取文件,加载类。

        优点:这个类型可以在编译期间未知,这个类名称可以在代码中出现,也可以配置在配置文件中,或键盘输入等方式来指定

      4、方式四:使用类的加载器:ClassLoader  (了解)

        Demo:

    1 ClassLoader classLoader = ReflectionTest.class.getClassLoader();
    2 Class clazz4 = classLoader.loadClass("com.java.Person");
    3 System.out.println(clazz4);

        该方法也需要传入一个类的全限定类名,该方法一般都是用在自定义类加载器对象去加载指定路径下的类

      

      注意:无论是哪种方式获取,Class 对象都是唯一的!!!、

     1     @Test
     2     public void test() throws ClassNotFoundException{
     3         Class<?> c1 = String.class;
     4         Class<?> c2 = "hello".getClass();
     5         Class<?> c3 = Class.forName("java.lang.String");
     6         Class<?> c4 = ClassLoader.getSystemClassLoader().loadClass("java.lang.String");
     7         System.out.println(c1 == c2);     // true
     8         System.out.println(c1 == c3);     // true
     9         System.out.println(c1 == c4);     // true
    10     }

    三、哪些类型可以有 Class 对象?

      所有的 Java 类型(包括基本数据类型、引用数据类型、void)被加载到内存后,或者编译器自动编译生成的 class 字节码,最终都会用一个 Class 对象表示。

      所有的 Java 类型,在内存中都表示为一个 Class 对象。Class 类的实例表示正在运行的 Java 应用程序中的类和接口。事实上,所有类型都可以表示为 Class 的实例对象。

    (1) class:外部类, 成员(成员内部类, 静态内部类), 局部内部类, 匿名内部类

    2interface: 接口

    3[]:数组,所有具有相同维数的数组共享同一个Class 对象

    4enum:枚举

    5annotation:注解@interface

    6primitive type:基本数据类型

    7void

      Demo:

     1     @Test
     2     public void test1(){
     3         Class<?> c1 = int.class;//基本数据类型
     4         Class<?> c2 = void.class;//void类型
     5         
     6         Class<?> c3 = String.class;//系统定义的类类型
     7         Class<?> c4 = Object.class;//
     8         Class<?> c5 = Class.class;//
     9         Class<?> c6 = Comparable.class;//接口类型
    10 
    11         //只要元素类型与维度一样,就是同一个Class
    12         Class<?> c7 = int[].class;
    13         int[] arr1 = new int[5];
    14         int[] arr2 = new int[10];
    15         System.out.println(arr1.getClass() == c7);
    16         System.out.println(arr2.getClass() == c7);
    17         Class c9 = String[].class;
    18         Class c10 = int[][].class;
    19         System.out.println(c7 == c9);
    20         System.out.println(c7 == c10);
    21         
    22         Class c11 = Override.class;//注解类型
    23         Class c12 = ElementType.class;//枚举类型
    24 
    25         //Class c9 = Student.class;//错误的,因为编译期间不存在
    26     }
  • 相关阅读:
    MQTT服务器搭建--Mosquitto用户名密码配置
    linux下c语言获取当前时间
    Linux下用C获取当前时间
    iptraf:一个实用的TCP/UDP网络监控工具
    CentOS配制FTP服务器,并且能用root权限登录
    centos6.4搭建ftp服务器
    两台Linux主机互传文件可以使用SCP命令来实现
    Linux 技巧:让进程在后台可靠运行的几种方法
    Linux 下 c 语言 聊天软件
    RobotFrameWork(五)控制流之if语句——Run Keyword If
  • 原文地址:https://www.cnblogs.com/niujifei/p/14881174.html
Copyright © 2020-2023  润新知