天天看点

初学JavaSE笔记——(十八)反射

一、类加载

        应用程序的启动:java  类名——>调用JVM,启动JVM进程,启动mian主线程,加载主类。

        应用程序的结束:1、所有代码执行完毕;2、存在没有处理的Exception、Error;3、System.exit(0);4、运行平台强制结束。

        1、类的生命周期

            (1)加载:把类的字节码文件加载到JVM的内存方法区中并且生成一个Class类型的对象。  

                ClassLoader(类加载器)加载(通过流的技术,也可自定义类记载器), 生成Class类型对象,通过Class类的方法操作类的属性、方法、构造器。           

            (2)连接:a、验证-字节码文件格式是否正确;b、准备-为类变量(静态变量)分配空间,默认初始化;c、解析-把符号引用替换成直接引用(指针:指向内存地址)。

            (3)初始化:当类被主动使用时,为类变量进行声明处和静态块处初始化。

                    1、当虚拟机Java命令运行启动类;

                    2、当创建某个类的新实例时;

                    3、当调用某个类的静态成员;

                    4、当初始化某个子类时,该子类的所有父类都会被初始化;

                    5、当使用反射方法强制创建某个类或接口的对象时;   Demo.class.newInstance();   

                    static final类型不能导致初始化;

            (4)使用

            (5)卸载

        2、类加载器

            根类加载器<——扩展类加载器<——系统类加载器<——自定义类加载器

            根类加载器:加载核心类库,d:\java\jdk1.8.0_144\jre\lib,c++写的,显示为null。

            扩展类加载器:加载扩展类库,lib\ext。

            系统类加载器:应用类加载器,classpath路径下的类。

            自定义类加载器:不是classpath路径,自己指定路径。

初学JavaSE笔记——(十八)反射

            父类委托机制(双亲):

            调用ClassLoader后,通过Class<?> c=findLoadedClass(name)查找此类是否被加载,已加载返回Class对象,未加载返回null;未加载,系统类加载器先不加载,查看父类加载器(扩展类加载器)是否存在,父类递归调用父类(根类加载器)加载,如根类加载器不存在,扩展类加载器加载,扩展类加载器不存在,系统类加载器加载。

                1、获得系统类加载器:ClassLoader.getSystemClassLoader().loadClass("包名.类名");

                2、加载并初始化:Class.forName("包名.类名",true,ClassLoader.getSystemClassLoader());true表示进行初始化,后面是指定加载器。

                                             Class.forName("包名.类名");

            自定义加载器:

            自定义类,属性为类的路径——>继承ClassLoader,重写findClass方法(用流把.class文件读出来、解析成方法区数据结构);

初学JavaSE笔记——(十八)反射

        ClassLoader类的defineClass(name,b[ ],0,len)将一个byte数组转换为Class类的实例;

        Class类的forName(name类的完全限定名,true初始化类,loader加载器)返回类关联的Class对象;

        FileInputStream类的read(byte[ ] b)从输入流中读入数组,返回读入的字节总数;

二、反射                

        反射是从方法区的字节码中动态的获得类中的信息。 

        获得 类名. class 对应的Class对象:

        a、Class<?> c=Class.forName("包名 . 类名");

        b、Class<类名> c=类名 . class;

        c、Class<? extends 类名> c=new 类名( ). getClass( );

        1、获取属性   

            Field [ ] fs=c.getDeclaredFields( );包括私有的>>区别于 Field [ ] fs=c.getFields( );获得属性不包括私有的。

            f.setAccessible(true);设置访问权限 ,也可通过安全管理器设置 System.setSecurityManager(new SecurityManager);

初学JavaSE笔记——(十八)反射

        2、获取方法     

            Method [ ] m=c.getDeclaredMethods( ); 

            Method类的invoke( )调用方法

初学JavaSE笔记——(十八)反射

        3、获得构造器

            Constructor cr=c.getDeclaredConstructor(参数类型.class);

            cr.newInstance(传值);

        4、获得注解

            Annotation [ ] an=c.getDeclaredAnnotations( );

            Arrays.stream( an ) . forEach( System.out ::println);

            用反射获得 子类 继承父类注解:

            Class<子类名> cs=子类名 . class;

            Annotation [ ] ans=cs . getField( "属性名") . getAnnotations( );//不用getDeclaredAnnotations( )

            Arrays.stream( ans) . forEach( System.out ::println);

三、注解

        @Overridec  重写

        @FunctionalInterface  函数式接口

        @Deprecated  已过时、过期

        @SuppressWarnings  镇压警告  -all    rawtypes、unused  原生类型,变量声明了,没有使用    unchecked 没有进行类型检查    serial 版本号

        自定义注解:@interface 注解名{ public/默认  类型  成员名( )  default  默认值;}

        Java元注解:@Target(ElementType . xxx),ElementType:CONSTRUCTOR 构造方法声明;FIELD字段声明(包括枚举常量);LOCAL_VARIABLE 局部变量声明;METHOD 方法声明;PACKAGE 包声明;PARAMETER 参数声明;TYPE 类、接口(包括注释类型)或枚举声明。

                            @Retention( )注解保留时间,RetentionPolicy . SOURCE/CLASS/RUNTIME

                            @Inherited( )子类可以继承类 类型声明时的注解

                            @Documented( )在生成的javadoc命令的API文档中显示注解信息