第7章 Java反射与注解
第7章 Java反射与注解
- 注解Annotation
- Annotation的作用
- Annotation的格式
- Annotation使用位置
- 内置注解
- 元注解
- 自定义注解
- 设置后自动生成的注解
- 2.反射机制
- 动态语言与静态语言
- 动态语言
- 静态语言
- Java不是动态语言
- Java反射机制
- 反射可以获取到private修饰的成员变量和方法
- 反射的应用
- Java反射的优缺点
- 反射的主要API
- API(Application Programming Interface)
- 通过对象来获取到它的Class,相当于逆过程。
- Class本身也是一个类
- Class类常用的方法
- 获取对象实例的方法
- 哪些类型可以有Class对象?
- 3.Java内存分析
- JVM(Java Virtual Machine)
- JRE(java runtime environment)
- JDK(java development kit)
- 什么时候发生类初始化
- 类的主动引用(一定发生初始化)
- 类的被动引用(不会发生初始化)
- 类加载的作用
- 双亲委派机制
- 反射操作泛型
- 映射工程
- ORM(Object relationship Mapping)
注解Annotation
Annotation的作用
不是程序本身,可以对程序做出解释(这一点和注释没有什么区别)
可以被其它程序,比如编译器读取
Annotation的格式
注解以 @注释名 在代码中存在的,还可以添加一些参数值
例如:@SuppressWarnings(value = “unchecked”)
Annotation使用位置
可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息
通过反射机制变成实现对这些元数据的控制
内置注解
@Override:定义在 java.lang.Override中,此注释只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明
实现一个新的方法
加上@Override注解后,表明这个方法可以被覆盖、重写
@Deprecated:定义在java.lang.Deprecated中,此注释可以用于修饰方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险,或者存在更好的选择
@SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息,与前面的两个注释不同,你需要额外添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了。
@SuppressWarnings(“all”)
@SuppressWarnings(“unchecked”)
@SuppressWarnings(value={“unchecked”, “deprecation”})
元注解
元注解的作用就是负责注解其它注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其它annotation类型作说明。
这些类型和它们所支持的类在 java.lang.annotation包可以找到
@Target 、@Retention、@Documented、@Inherited
@Target:用于描述注解的使用范围,即:被描述的注解可以在什么地方使用
@Retention:表示需要什么保存该注释信息,用于描述注解的生命周期
级别范围:Source < Class < Runtime
@Document:说明该注解被包含在java doc中 (Java 说明文档)
@Inherited:说明子类可以集成父类中的注解
自定义注解
使用 @interface自定义注解时,自动继承了 java.lang.annotation.Annotation接口
- @interface 用来声明一个注解,格式:public @interface 注解名 {定义内容
- 其中的每个方法实际上是申明了一个配置参数
- 方法的名称j就是参数的类型
- 返回值类型就是参数的类型(返回值只能是基本数据类型,Class,String,enum)
- 通过default来申明参数的默认值
- 如果只有一个参数成员,一般参数名为 value
- 注解元素必须要有值,我们定义元素时,经常使用空字符串或者0作为默认值
设置后自动生成的注解
/*** 自定义注解** @author: Larray* @create: 2020-03-28-22:57*/
2.反射机制
动态语言与静态语言
动态语言
动态语言是一类在运行时可以改变其结构的语言:例如新的函数,对象,甚至代码可以被引进,已有的函数可以被删除或是其它结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构
主要的动态语言有:Object-c、C#、JavaScript、PHP、Python等
静态语言
与动态语言相比,运行时结构不可变的语言就是静态语言。例如Java、C、C++
Java不是动态语言
,但是Java可以称为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制来获取类似于动态语言的 特性,Java的动态性让编程的时候更加灵活。
Java反射机制
反射:正常方式的逆过程
什么是反射
Java Reflection:Java反射是Java被视为动态语言的关键,反射机制运行程序在执行期借助于Reflection API 去的任何类内部的信息,并能直接操作任意对象的内部属性及方法。
Class c = Class.forName("java.lang.String")
在加载完类后,在堆内存的方法区就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像一面镜子,透过这个镜子看到类的结构,所以我们形象的称之为:反射
反射可以获取到private修饰的成员变量和方法
反射的应用
在运行时判断任意一个对象所属类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时候处理注解
生成动态代理
…
Java反射的优缺点
优点:可以实现动态创建对象和编译,体现出很大的灵活性
缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作。也就是说new创建和对象,比反射性能更高
反射的主要API
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器
…
API(Application Programming Interface)
应用程序接口(英语:Application Programming Interface,简称:API),又称为应用编程接口,就是软件系统不同组成部分衔接的约定。由于近年来软件的规模日益庞大,常常需要把复杂的系统划分成小的组成部分,编程接口的设计十分重要。程序设计的实践中,编程接口的设计首先要使软件系统的职责得到合理划分。良好的接口设计可以降低系统各部分的相互依赖,提高组成单元的内聚性,降低组成单元间的耦合程度,从而提高系统的维护性和扩展性。
/*** 反射Demo** @author: Larry* @create: 2020-03-29-8:21*/
public class ReflectionDemo {public static void main(String[] args) throws ClassNotFoundException {// 通过反射获取类的Class对象Class c1 = Class.forName("com.ctgu.entity.User");Class c2 = Class.forName("com.ctgu.entity.User");Class c3 = Class.forName("com.ctgu.entity.User");System.out.println(c1.hashCode());System.out.println(c2.hashCode());System.out.println(c3.hashCode());}
}
通过对象来获取到它的Class,相当于逆过程。
Class本身也是一个类
Class对象只能由系统建立对象
一个加载的类在JVM中只会有一个Class实例
一个Class对象对应的是一个加载到JVM中的一个.class文件
每个类的实例都会记得自己是由哪个Class实例所生成
通过Class可以完整地得到一个类中所有被加载的结构
Class类是Reflection的根源,针对任何你想动态加载、运行的类、唯有先获得相应的Class对象
Class类常用的方法
ClassforName(String name):返回指定类name的Class对象
newInstance():调用缺省构造函数,返回Class对象的一个实例
getName():返回此Class对象所表示的实体(类,接口,数组或void)的名称
getSuperClass():返回当前Class对象的父类Class对象
getinterfaces():返回当前对象的接口
getClassLoader():返回该类的类加载器
getConstructors():返回一个包含某些Constructor对象的数组
getMethod(String name, Class… T):返回一个Method对象,此对象的形参类型为paramsType
getDeclaredFields():返回Field对象的一个数组
获取对象实例的方法
若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
Class clazz = Person.class;
已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class clazz = person.getClass()
已经一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取,HIA可能抛出ClassNotFoundException
Class clazz = Class.forName(“demo01.Sutdent”)
内置数据类型可以直接通过 类名.Type
还可以利用ClassLoader
哪些类型可以有Class对象?
class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
interface:接口
[]:数组
enum:枚举
annotation:注解@interface
primitive type:基本数据类型
void
3.Java内存分析
java内存分为以下三部分
堆
存放new的对象和数组
可以被所有的线程共享,不会存放别的对象引用
栈
存放基本变量(会包含这个基本类型的具体数值)
引用对象的变量(会存放这个引用在对堆里面的具体地址)
方法区
可以被所有线程共享
包含了所有的class和static变量
JVM(Java Virtual Machine)
JVM是Java Virtual Machine(Java虚拟机)的缩写,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。
JRE(java runtime environment)
JRE是java runtime environment(java运行环境)的缩写。光有JVM还不能让class文件执行,因为在解释class的时候JVM需要调用解释所需要的类库lib。在JDK的安装目录里你可以找到jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和lib合起来就称为jre。
JDK(java development kit)
JDK是java development kit(java开发工具包)的缩写。每个学java的人都会先在机器上装一个JDK,那 让我们看一下JDK的安装目录。在目录下面有六个文件夹、一个src类库源码压缩包、和其他几个声明文件。其中,真正在运行java时起作用的是以下四个文件夹:bin、include、lib、jre。现在我们可以看出这样一个关系,JDK包含JRE,而JRE包含JVM。
什么时候发生类初始化
类的主动引用(一定发生初始化)
当虚拟机启动,先初始化main方法所有在类
new 一个类的对象
调用类的静态成员(除了 final常量)和静态方法
使用 java.lang.reflect包的方法对类进行反射调用
当初始化一个类,如果其父类没有被初始化,则会先初始化它的父类
类的被动引用(不会发生初始化)
当访问一个静态域时,只有真正的申明这个域的类才会被初始化,如:当通过子类引用父类的静态变量,不会导致子类初始化
通过数组定义类引用,不会触发此类的初始化
引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池了)
类加载的作用
类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成了一个代表这个类的 java.lang.Class对象,作为方法区中类数据的访问入口。
类缓存:标准的JavaSE类加载器可以按要求查找类,但是一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象
双亲委派机制
定义一个:java.lang.string 包,无法创建
因为类在加载的时候,会逐级往上
也就是说当前的系统加载器,不会马上的创建该类,而是将该类委派给 扩展类加载器,扩展类加载器在委派为根加载器,然后引导类加载器去看这个类在不在能访问的路径下,发现 string包已经存在了,所以就无法进行,也就是我们无法使用自己自定义的string类,而是使用初始化的stirng类
当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
采用双亲委派的一个好处是比如加载位于rt.jar 包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个Object 对象
反射操作泛型
Java采用泛型擦除机制来引入泛型,Java中的泛型仅仅是给编译器Java才使用的,确保数据的安全性和免去强制类型转换的问题,但是一旦编译完成后,所有的泛型有关的类型全部被擦除
为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是有何原始类型齐名的类型。
ParameterizedType:表示一种参数化类型,比如Collection
GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
TypeVariable:是各种类型变量的公共父接口
WildcardType:代表一种通配符类型的表达式
映射工程
ORM对象关系映射,可实现增删改查的功能
ORM(Object relationship Mapping)
即为:Object relationship Mapping,对象关系映射
类和表结构对应
属性和字段对应
对象和记录对应
第7章 Java反射与注解相关推荐
- java反射和注解开发(备java基础,javaee框架原理)-任亮-专题视频课程
java反射和注解开发(备java基础,javaee框架原理)-5358人已学习 课程介绍 Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明. ...
- 第三章. Java反射
第三章. Java反射 1. 反射 2. 反射接口 2.1获取Class方式: 2.2 获取成员变量并调用 2.3 获取成员方法并调用 2.4 获取构造方法并调用 2.5 获取父类信息 3. 反射应用 ...
- java反射获取注解id,通过反射获取注解(Annotation)
以下实例,定义一个注解.通过反射获取. 主要功能:为所注解过的参数和方法附加一些信息可以获取. 定义注解. import java.lang.annotation.*; @Retention(Rete ...
- 注解 java 反射_java注解和反射
2020-05-19 注解的作用: 不是程序本身,可以对程序做出解释,和注释有相似之处. 可以被其他程序(如编译器)所读取. 注解的格式:以"@注解名"在代码上存在,还可以在其中添 ...
- Java反射自定义注解底层设计原理
文章目录 一.反射 1. 反射概念 2. 反射机制的优缺点 3. 反射的用途 4. 反射技术的使用 5. 反射常用的Api 6. 反射执行构造函数 7. 反射执行给属性赋值 8. 反射执行调用方法 二 ...
- java 反射 参数 注解_Java编程之反射中的注解详解
"注解"这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题.我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些"注解&quo ...
- Java反射+自定义注解实现配置文件数组加载(实现@ConfigurationProperties(xxx))
Java.Rust 技术交流群: 783303214 一.背景 最近有小朋友问我,怎么样在.properties文件中配置数组参数,我给他举了上篇文章中的注解@ConfigurationPropert ...
- Java反射——反射机制问题——第一章
Java反射--反射机制问题--第一章 Java反射--Class类--第二章 Java反射--类加载--第三章 Java反射--反射获取类的结构信息--第四章 文章目录 1:一个需求引出反射 2:反 ...
- 第1章 Java语言概述
第1章 Java语言概述 声明 0. Java语言应用场景 1. 软件开发介绍 2. 计算机编程语言介绍 3. Java语言概述 4. Java程序运行机制及运行过程 5. Java的环境搭建 5. ...
最新文章
- 旷视MegEngine核心技术升级
- AI生成中国山水画!普林斯顿姑娘本科毕业作品,骗过70%中国人
- JAVA入门笔记·JAVA名词及环境搭建
- 【caffe解读】 caffe从数学公式到代码实现2-基础函数类
- VTK:突出坏细胞用法实战
- python 一行_一行 Python 代码搞定炫酷可视化
- Ubuntu10.04制作官方源镜像以及搭建本地源
- ArcEngine开发 退出系统报错
- 在Ubuntu 13.10 下安装支持SSL的Apache
- kido机器人没反应_机器人不能钩的三个英雄,章鱼妈上榜,钩中图四我方直接团灭!...
- java 字符界面 curses_[C++]Linux之图形界面编程库[curses库]之入门教程
- php十二星座_php计算十二星座的函数代码
- 中国甲腈行业市场供需与战略研究报告
- 【Shell】获取文件名和扩展名
- python怎么恢复默认窗口,如何恢复python编程环境spyder的窗口
- MySQL索引实现、MySQL索引原理、索引下推、索引覆盖、索引失效
- 信息技术知识点汇总(必修)
- 视频播放加密功能的演示
- 基于双二阶广义积分器(DSOGI)的软件锁相环需求的根源及s域仿真
- 手机--修改dns服务器地址,DNS怎么修改 电脑和手机设置DNS全攻略
热门文章
- CAM350技巧【导入gerber文件】【单位尺度设置】【CAM测量】【操作说明与快捷键】【Cam350显示钻孔异常解决】
- Buuctf Misc小明的保险箱(暴力破解)
- 计算机物质与结构微命令,2015年哈尔滨工程大学082700核科学与技术考研大纲(官方)...
- LaTeX数学公式的矩阵、多行公式
- MySQL创建索引,各种索引的创建及举例
- 通才与专家_成为通才
- 具有交叉信号模式的色散信号的群延迟(色散曲线)估计和模式分离(Matlab代码实现)
- 好用的Mac虚拟机 Parallels Desktop
- 使用PSFTP进行Windows与Linux远程服务器的上传下载
- MySQL学习-表记录的查询操作