注解_反射_类加载器机制_深入类加载器

第一章 注解

1.内置注解

  • @Override
    – 定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方 法声明打算重写超类中的另一个方法声明。

  • @Deprecated
    – 定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类 ,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更 好的选择。

  • @SuppressWarnings
    – 定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息 。
    – 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参 数值都是已经定义好了的,我们选择性的使用就好了,参数如下:
    在这里插入图片描述
    – @SuppressWarnings(“unchecked”)
    – @SuppressWarnings(value={“unchecked”, “deprecation”})

2.自定义注解

直接上一个实例,然后在解释。

自定义注解代码

@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtAnnotation01 {
	//定义参数的默认值
	String studentName() default "";
	int age() default 0;
	//没有值的时候默认为-1.
	int id() default -1;   //String indexOf("abc")  -1
	String[] schools() default {"清华大学","北京大学"};
	
}

注解的使用类

/**
 * 测试自定义注解的使用
 *
 */
@SxtAnnotation01
public class Demo02 {
	
	@SxtAnnotation01(age=19,studentName="老高",id=1001,schools={"北京大学","北京航空航天大学"})
	public void test(){
	}
	@SxtAnnotation02("aaaa")
	public void test2(){
	}
	
}
  • @interface
    – 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口 ,作用就是用来声明一个注解。格式为:public @interface 注解名 {定义体}

  • @Target
    –作用:
    – 用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
    在这里插入图片描述
    – @Target(value=ElementType.TYPE)

  • @Retention
    – 作用:
    —表示需要在什么级别保存该注释信息,用与描述注解的生命周期
    在这里插入图片描述

第二章 反射机制(reflection)

1.简介

存在于java.lang.Class包中
–程序在运行状态中,可以动态的加载一个只有名称的类,对于任意一个一家在的类,都能狗知道这个累的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法和属性。
例如:
Class c = Class.forName("com.wang.pojo.User);
加载类完后,在对内存就会产生一个Class类型的对象(一个类只有一个Class类对象),这个对象就包含完整的累的结构信息。

在这里插入图片描述

2.获取Class类的对象的三个方法

2.1运用Class.forName()(最长被使用)★★★★★

Class c = Class.forName("com.wang.pojo.User);

  • 获取构造方法
    • c.getConstructors();获取(本类、父类和接口)全部公共构造方法
    • c.getDeclaredConstructor(String.class)获取单个构造方法
  • 获取属性
    • c.getFields();获取(本类、父类和接口)全部公共属性
    • c.getDeclaredFields();获取当前类的所有属性包括私有
  • 获取方法
    • c.getMethods();获取(本类、父类和接口)全部公共方法
    • c.getDeclaredMethods();获取当前类的所有方法包括私有
    • Method m = c.getDeclaredmethod(“study”,String.class)//调用User类中的study方法,String.class是参数类型
      – m.setAccseeible(true)//把访问私有权限打开
      – m.invoke(new User(),“学习”)//执行方法并传入参数值
  • 获取接口
    • c.getInterfaces();获取(本类、父类和接口)全部公共接口
  • 获取所有父类
    • c.getSuperclass();获取(本类、父类和接口)全部父类
2.2运用getClass()

new User().getClass();
获取数据和第一种方法获取的方法一样

2.3运用 类名.class

User.class
获取数据和第一种方法获取的方法一样

第三章 类的加载机制

类的加载全过程

  • 为什么研究类加载全过程?
    – 有助于了解JVM运行过程
    – 更深入了解java动态性,(解热部署、动态加载),提高程序的灵活性。

  • 类加载机制
    – JVM把class文件加载到内存,并对数据进行校验、解析和初始化,最终形成 JVM可以直接使用的Java类型的过程。
    在这里插入图片描述

  • 加载

    将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代 表这个类的java.lang.Class对象,作为方法区类数据的访问入口。这个过程需要类加载器参与。

在这里插入图片描述

  • 链接 将Java类的二进制代码合并到JVM的运行状态之中的过程

    验证: – 确保加载的类信息符合JVM规范,没有安全方面的问题。
    准备: – 正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
    解析 – 虚拟机常量池内的符号引用替换为直接引用的过程

  • 初始化

    – 初始化阶段是执行类构造器()方法的过程。类构造器()方法是由编译器自动收集 类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
    – 当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先出发其父类的初始化
    – 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。

  • 类的主动引用(一定会发生类的初始化)

    new一个类的对象
    – 调用类的静态成员(除了final常量)和静态方法
    – 使用java.lang.reflect包的方法对类进行反射调用
    – 当虚拟机启动,java Hello,则一定会初始化Hello类。说白了就是先启动main方法所在的类
    – 当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类

  • 类的被动引用(不会发生类的初始化)

    – 当访问一个静态域时,只有真正声明这个域的类才会被初始化
    • 通过子类引用父类的静态变量,不会导致子类初始化
    – 通过数组定义类引用,不会触发此类的初始化
    – 引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了)

在这里插入图片描述

简单描述一下上图的代码 加载顺序。

在执行这段代码时,
首先会加载Demo01类,在方法区生成一个Dome01类的静态数据,同时会在堆内存中形成一个java.lang.Class对象(反射对象),代表Demo01类,通过堆里的Demo01类可以获取方法区中demo01类的数据结构,从而操作数据。
接下来会加载A的静态数据结构,会初始化static的代码。同时也会在堆内存中形成一个反射对象。
开始执行main方法,会在栈中形成一个mian方法栈帧。如果main方法里面有其他方法会进行压栈操作,main方法中有局部变量a=null,当new A();时,调用构造器方法,构造A,进行压栈,同时会在堆中生成一个A的对象,把A地址赋给a,然后a.width就会在方法区的数据中找到相映的值。

emmm,说到这就会想起那个经典的面试题,static代码块,构造代码块,构造函数,普通代码块的面试题。
执行顺序 静态代码块>构造代码块>构造函数>普通代码块吗,静态代码块只执行一次,构造代码块会每调一次执行一次。

类加载器的作用

  • 类加载器的作用
    • 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法 区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class 对象,作为方法区类数据的访问入口。
  • 类缓存
  • 标准的Java SE类加载器可以按要求查找类,但一旦某个类被加载到类加载 器中,它将维持加载(缓存)一段时间。不过,JVM垃圾收集器可以回收 这些Class对象。

类加载器的层次结构(树状结构)

在这里插入图片描述
重点是树状结构,类加载器用的模式是代理模式。使用的是双亲委托机制。相对与比较安全,而且没有线程问题。
代理模式的原理。当一个类加载时,首先进入自己的类,把加载的任务给父类加载(应用程序类加载器),父类也不加载转发给父类(扩展类加载器),扩展类也不加载,转发给启动类,启动类会加载,然后一层一层地传递给自定义类。
这种代理模式的好处是。保证不会出现用户自己能定义java.lang.Object类的情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值