
本文共 3478 字,大约阅读时间需要 11 分钟。
注解 annotation
@Overrride
@Deprecated 不推荐使用
@SuppressWarning 镇压警告,抑制警告
元注解
负责注解其他注解
@Target 描述注解使用范围
@Retention 表示需要在什么级别保存改注解信息,描述注解的声明周期 SOURCE < CLASS < RUNTIME
@Decumented 说明改注解将被包含再javadoc
@Inherited 说明子类可以继承父类中的该注解
1、使用@interface 自定义注解时,自动继承了java.lang.annotation.Annotation接口
2、 方法的名称就是参数的名称
3、返回值的类型就是参数的类型,返回值只能是Class、String、enum
4、可以通过default,声明默认值
反射
Java.Reflection
1、java是一个静态语言,反射机制让java称为一个准动态语言
动态语言:在运行时可以改变其结构的语言 js php c# python
静态语言:运行时结构不改变
java:不是动态语言,但可以称为“准动态语言”,Reflection(反射)是关键
Class c = Class.forName("java.lang.String");在Object类中,定义了public final Class getClass();
反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并直接操作任意对象的内部属性和方法
加载完类之后,jre在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含完成的类的结构信息。
我们可以通过这个对象看到类的结构。这个对象就像一面镜子,通过这个镜子可以看到类的结构,所以,我们形象说:反射
Class对象只能由系统创建
一个Class对象对应的是一个加载到JVM中的一个class文件
每个类的实例都会记得自己是由那个Class实例生成的
Class类是Reflection的根源,要想动态加载、运行的类,要先获得Class对象
正常方式 : 引用包 ----> new 实例化 -----> 获得实例化对象
反射方式: 实例化对象 ------> getClass() 方法 -------> 获得完整的“包类”名称
java 反射机制提供的功能
1、在运行是判断一个对象所属的类
2、在运行是构造任意一个类的对象
3、在运行是判断一个类所具有的成员变量和方法
4、在运行是获取泛型信息
5、在运行时调用任意一个对象的成员变量和方法
6、在运行时处理注解
7、生成动态代理 AOP面向切面编程
、、、、、、、
优点:灵活
缺点:性能低
主要API
java.lang.Class
java.lang.reflect.Method 类的方法
java.lang.reflect.Field 类的成员变量
java.lang.reflect.Constructor 类的构造器
Class类常用方法
static Class.forName
Object newInstance()
getName()
Class getSuperClass()
Class[] getinterfaces 获得当前对象的接口
ClassLoader getClassLoader 返回类的类加载器
Contructor[] getConstructors() 返回一个类的构造器
Method getMethod(String name, Class … T) 返回一个Method对象,此对象的形参为paramType
Field[] getDeclaredFields() 返回Field对象的一个数组
获得Class类的实例
// 1Class clazz = Person.class;//2Class clazz = person.getClass();//3 Class clazz = Class.forName("java.lang.String");//4//内置基本数据类型,直接用类名.Type// 5// 还可以使用ClassLoader
哪些类型由Class对象
class
interface
[] : 数组
enum
annotation
primitive type: 基本数据类型
void:
java内存分析
堆
1、 可以存放new对象和数组
2、可以被所有线程共享
3、不会存放别的对象引用
栈
1、存放基本变量类型(包含这个基本类型的具体数值)
2、引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区
1、特殊的堆
2、可以被所有线程共享
3、包含了所有的class和static变量
当程序主动使用某个类时,如果该类还没有加载到内存中,那么系统会通过下面三个步骤对这个类进行初始化
1、类的加载 load
将类的class文件读入内存,将静态数据转换成方法区的运行时数据结构,并为他创建一个java.lang.Class对象,在堆中
2、类的链接 link
将类的二进制代码合并到jvm的运行状态中的过程
验证:确保加载的类信息符合JVM规范,没有安全方面的问题
准备:正式为类变量(static)分配内存,并设置默认初始值的阶段,这些内存都是在方法区中进行分配
解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
3、类的初始化 Initialize
jvm 负责对类进行初始化
执行类构造器()方法的过程。类构造器()方法由编译器自动收集类中所有类变量的赋值动作和静态代码块中语句合并产生的。
当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先出发其父类的初始化
虚拟机会保证一个类的() 方法在多线程环境中被正确加锁和同步
自己的理解:
无非就是加载、链接、初始化,
加载是要读文件到内存中,也就是class文件字节码加载到内存中
然后加载的时候,顺手将静态数据转换成方法区的运行时数据结构
链接:读入内存,肯定要运行,链接准备启动的过程
首先验证,看看是不是安全的。
然后准备,为静态变量分配内存,这个时候就用到了加载时方法区的数据结构
最后解析,将虚拟机常量池中的符号引用替换成直接引用(地址)的过程。因为之前没分配内存,所以先使用符号引用,分配好内存之后,替换成直接引用
初始化:执行类的构造器()的过程
链接的时候分配了内存,但是初始化赋值,这里需要使用()方法来初始化
()时编译期间自动收集类所有中类变量的赋值动作和静态代码块中语句合并产生的。
类构造器时构造类信息的,不是够在类对象的构造器。
如果父类还没有初始化,先出发父类的初始化,
jvm保证()在多线程环境在被正确加锁和同步
什么时候发生类的初始化
类的主动引用(一定发生)
1、jvm启动,先初始化main方法所在的类
2、new一个类的对象
3、调用类的静态成员(除了final常量)和静态方法
4、使用java.lang.reflect包的方法对类进行反射调用
5、当初始化一个类,父类没有被初始化,则会先初始化他的父类
类的被动引用(不会发生类的初始化)
1、访问一个静态域时,只有真正声明这个域的类才会被初始化
如:当通过子类引用访问父类的静态变量,不会导致子类的初始化
2、通过数组定义类引用,不会触发类的初始化
3、应用常量不会出发类的初始化(常量在链接阶段就存入调用类的常量池中了)
类加载器的作用
**类缓存:**标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,他将维持加载(一段实践),不过JVM来及回收机制可以回收这些Class对象
类加载器种类
引导类加载器 :用c++编写,jvm自带的类加载器,负责java平台核心库(rt.jar),用来装载核心库,该类加载器无法直接获取
扩展类加载器:负责jre/lib/ext目录下的jar包,包括-D java.ext.dirs指定目录下的jar包装入工作库
系统类加载器:负责java -classpath或 -D java.class.path所指的目录下的jar包装入工作,最常用的加载器
创建运行时类的对象
通过反射获取运行时类的完整结构
Field
Method
Constructor
Superclass
Interface
Annotation
发表评论
最新留言
关于作者
