Java之注解与反射
Java之注解与反射
注解(Annotation)简介
注解(Annotation)是从JDK5.0引入的新技术
Annotation作用:注解(Annotation)可以被其他程序如编译器等读取
Annotation格式:@"注释名",当然可以添加一些参数值(形如:
@Retention(RetentionPolicy.RUNTIME)
)它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
Annotation
注解可以通过反射去读取
注解的定义
内置注解
@Override
定义在java.lang.Override
中,此注释只适用于修辞方法,表示声明一个方法打算重写超类中的另一个方法。
@Deprecated
定义在java.lang.Deprecated
中,此注释只适用于修辞方法,属性,类,表示不支持使用这样的元素
@SupperWarnings
定义在java.lang.SupperWarnings
中,用来抑制编译告警时的警告信息,需要添加一个参数才能正确使用
元注解
元注解的作用就是负责注解其他注解,java定义了4个标准的meta-annotation类型:@Target/@Retention/@Document/@Inherited
元注解中重点为@Target
和@Retention
@Target:用于描述注解的作用范围(比如作用在某个类或某个方法)
@Retention:描述注解的生命周期,对于反射就是可以在什么时候获取该注解(SOURCE<CLASS<RUNTIME)
自定义注解
使用@interface可以自定义注解。
@interface 注解名{
//自定义的注解内容
//如果参数只有一个值,建议写value
String value();
}
例子
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class TestAnnotationDemo3 {
//测试自定义注解
@MyAnnotation2("qifei")
@MyAnnotation(name = "wuhu", id = 10)
public void test(){
System.out.println("test");
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD}) //作用于 方法和类
@Retention(RetentionPolicy.RUNTIME) //作用于 运行时
@interface MyAnnotation{
//定义参数
String[] name() default ""; //参数默认为空,参数名为name
int id();
}
@Target(value = {ElementType.TYPE,ElementType.METHOD}) //作用于 方法和类
@Retention(RetentionPolicy.RUNTIME) //作用于 运行时
@interface MyAnnotation2{
//如果参数只有一个值,建议写value
String value();
}
反射(Reflection)机制
Java反射(Reflection)是Java非常重要的动态特性,通过使用反射我们不仅可以获取到任何类的成员方法、成员变量、构造方法等信息,还可以动态创建Java类实例、调用任意的类方法、修改任意的类成员变量值等。注解和反射是各种java web框架的底层实现机制与灵魂。
Class类
反射首先要用到的就是Class类,Class类是一个描述类的类,但是Class本身也是一个类,一个在内存中加载的类在JVM中只会有一个对应的Class的实例话对象,通过Class可以完整的得到一个类中所有被加载的结构。Class类就是反射的根源
获取Class类实例
1、已知具体的类,通过类的class属性获取
Class c = Object.class;
2、已知某个类的实例,通过调用getClass()方法获取class对象
Person person = new Person();
Class c = person.getClass();
3、已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取class对象
Class c = Class.forName("com.reflection.demmo");
4、基本内置类型的包装类的Type属性获取class对象
Class c = Integer.TYPE;
例子:
//测试class类的创建方式
public class ReflactionDemo02 {
public static void main(String[] args) throws ClassNotFoundException {
Person student = new Student();
System.out.println("这个人是:" + student.name);
//获取Student类的class实例对象
//1、通过getClass() 获得
Class c1 = student.getClass();
System.out.println(c1.hashCode());
//2、通过Class类的forName() 获得
Class c2 = Class.forName("com.reflaction.Student");
System.out.println(c2.hashCode());
//3、通过student类的class属性获得
Class c3 = Student.class;
System.out.println(c3.hashCode());
//4、基本内置类型的包装类的Type属性
Class c4 = Integer.TYPE;
System.out.println(c4.hashCode());
//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
这个人是:学生
1627674070
1627674070
1627674070
1360875712
class com.reflaction.Person
具有Class实例对象的数据类型
//所有类型的class对象
public class ReflactionDemo03 {
public static void main(String[] args) {
Class c1 = Object.class; //类
Class c2 = Runnable.class; //接口
Class c3 = String[].class; //一维数组
Class c4 = String[][].class; //二维数组
Class c5 = Override.class; //注解
Class c6 = ElementType.class; //枚举
Class c7 = Integer.class; //基本数据类型包装类
Class c8 = void.class; //void
Class c9 = Class.class; //Class
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
}
}
class java.lang.Object
interface java.lang.Runnable
class [Ljava.lang.String;
class [[Ljava.lang.String;
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
反射获取类运行时的完整结构
Field()
Field[] fields = c1.getFields(); //getFields 只能找到pubilc属性
fields = c1.getDeclaredFields(); //getDeclaredFields 可以找到所有属性
for (Field field : fields) {
System.out.println(field);
}
Method()
getMethods()
获得本类和继承类的所有public方法
getDeclaredMethods()
获取本类的所有方法
getMethod("方法名", 参数类型.class)
获得指定的方法
//获得本类和继承类的所有public方法
Method[] methods = c1.getMethods();
for (Method method : methods
) {
System.out.println("getMethods(): " + method);
}
//获取本类的所有方法
methods = c1.getDeclaredMethods();
for (Method method : methods
) {
System.out.println("getDeclaredMethods(): " + method);
}
//获得指定的方法
Method setName = c1.getMethod("setName", String.class);
Method getName = c1.getMethod("getName");
System.out.println(setName);
System.out.println(getName);
Constructor()
//获取所有的构造器
Constructor[] constructors = c1.getConstructors(); //获取本类和父类的所有构造方法
for (Constructor constructor : constructors
) {
System.out.println(constructor);
}
System.out.println("=====================================");
constructors = c1.getDeclaredConstructors(); //获取本类所有构造方法
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("=====================================");
//获取指定的构造器
Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
System.out.println(constructor);
反射类构造器获得实例化对象
- 反射获得User类的class对象
Class.forName()
- 调用有参或无参构造方法实例化对象
class.newInstance()
public static void main(String[] args) throws Exception{
//反射获得User类的class对象
Class c1 = Class.forName("com.reflaction.User");
User user = (User) c1.newInstance(); //调用无参构造实例化对象
System.out.println(user);
//获得有参构造方法
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
//通过构造器获得实例话对象
User ago = (User) constructor.newInstance("ago", 18, 1); //有参构造获得实例化对象
System.out.println(ago);
}
User{name='null', age=0, id=0}
User{name='ago', age=18, id=1}
反射获取调用普通方法
方式1: 反射获取目标类的class对象(Class.forName()) ==> 获取有参构造器(class.getDeclaredConstructor()) ==> 获取目标类实例化对象(constructor1.newInstance(param1, param2, param3 ,...)) ==> 调用方法(实例化对象.Method())
Class c2 = Class.forName("com.reflaction.User");
Constructor constructor1 = c2.getDeclaredConstructor(String.class, int.class, int.class);
User zh1z3ven = (User) constructor1.newInstance("zh1z3ven", 20, 2);
System.out.println(zh1z3ven.getAge());
System.out.println(zh1z3ven.getName());
zh1z3ven.setId(20);
System.out.println(zh1z3ven.getId());
方式2: 反射获取目标类class对象(Class.forName()) ==> 获取指定方法(class.getMethod("方法名", 参数)) ==> 激活执行方法(.invoke(目标对象, 参数))
Class c2 = Class.forName("com.reflaction.User");
User user2 = (User) c2.newInstance();
Method setName = c2.getMethod("setName", String.class);
setName.invoke(user2, "kfei");
System.out.println(user2.getName());
反射操作属性
- 获取class对象
class.getDeclaredField("属性名")
获取属性.set()
方法设置属性- 若为private修饰,出现无权限操作异常,可用
.setAccessible(true)
关闭安全检测,获取操作权限
Class c3 = Class.forName("com.reflaction.User");
User user4 = (User) c3.newInstance();
Field name = c3.getDeclaredField("name");
name.setAccessible(true);
name.set(user4 ,"zgo");
System.out.println(user4.getName());
Invoke(Object obj, Obj... args)
Object对应原方法返回值,若无返回值,返回null
若原方法为静态方法,形参Object obj可为null
若原方法形参列表为空,Obj... args可为null
若原方法声明为private,在调用invoke()前,显示调用方法对象的
.setAccessible(true)
方法,关闭安全检测,获取访问权限
反射调用Runtime()
import org.apache.commons.io.IOUtils;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class RuntimeExecDemo {
public static void main(String[] args) throws Exception{
String command = "ifconfig";
Class c = Class.forName("java.lang.Runtime"); //获取Runtime类的class对象
Constructor constructor = c.getDeclaredConstructor(); //获取构造器
constructor.setAccessible(true); //关闭安全检测,暴力反射
Object runtime = constructor.newInstance(); //构造runtime对象
Method exec = c.getMethod("exec", String.class); //获取exec方法
Process process = (Process) exec.invoke(runtime, command); //激活执行exec
//获取命令回显结果
InputStream inputStream = process.getInputStream(); //获取process输入流中输出的数据
String ifconfig = IOUtils.toString(inputStream, "GBK"); //字节流转字符流
System.out.println(ifconfig); //打印结果
}
}
反射操作泛型
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class TestFanXingDemo {
public void test01(Map<String, User> map, List<User> list){
System.out.println("test01");
}
public Map<String, User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = TestFanXingDemo.class.getMethod("test01", Map.class, List.class);
method.setAccessible(true); //关闭安全检测,暴力反射
Type[] genericParameterTypes = method.getGenericParameterTypes(); //获得泛型的参数类型
for (Type genericParameterType : genericParameterTypes) {
System.out.println("#genericParameterType: " + genericParameterType); //遍历泛型类型
if (genericParameterType instanceof ParameterizedType){ //判断泛型参数类型是否是参数化类型
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); //获得真实参数信息
//循环遍历参数
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
}
反射操作注解
ORM = Object Relationship Mapping ==> 对象关系映射
类和表对应,类的属性和表的字段对应,对象和记录对应
利用注解和反射完成类和表的结构的映射关系
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class TestDemo12 {
//反射操作注解
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.reflaction.Student2");
//通过反射获得全部注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value值
TableStudent tableStudent = (TableStudent) c1.getAnnotation(TableStudent.class);
String value = tableStudent.value();//获取注解的value
System.out.println(value);
//获取指定类的注解value
Field f = c1.getDeclaredField("name");
FieldStudent annotation = f.getAnnotation(FieldStudent.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@TableStudent("db_student")
class Student2{
@FieldStudent(columnName = "db_id", type = "int", length = 10)
private int id;
@FieldStudent(columnName = "db_age", type = "int", length = 10)
private int age;
@FieldStudent(columnName = "db_name", type = "varchar", length = 3)
private String name;
public Student2() {
}
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE) //作用范围为类
@Retention(RetentionPolicy.RUNTIME) //作用为运行时可获取
@interface TableStudent{
String value();
}
//属性的注解
@Target(ElementType.FIELD) //作用范围为类
@Retention(RetentionPolicy.RUNTIME) //作用为运行时可获取
@interface FieldStudent{
String columnName();
String type();
int length();
}
结尾
参考文章:
https://www.cnblogs.com/nice0e3/p/13498308.html
https://www.cnblogs.com/nice0e3/p/13494147.html
关于Process类、反射操作泛型和注解因为暂时刚需不大且还没研究透,记录的较少,后门会另出文章记录一下。
到此JavaSE部分基本就学完了(除了GUI)后面要开JavaWeb和框架了,冲冲冲!
Java之注解与反射的更多相关文章
- Java基于注解和反射导入导出Excel
代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...
- 使用Java元注解和反射实现简单MVC框架
Springmvc的核心是DispatcherServlet来进行各种请求的拦截,进而进行后续的各种转发处理.流程图如下: 说明:客户端发出一个http请求给web服务器,web服务器对http请求进 ...
- java自定义注解与反射
java注解与反射一.Java中提供了四种元注解,专门负责注解其他的注解,分别如下 1.@Retention元注解,表示需要在什么级别保存该注释信息(生命周期).可选的RetentionPoicy参数 ...
- java使用注解和反射打造一个简单的jdbc工具类
a simple jdbc tools 如有转载和引用,请注明出处,谢谢 1. 定义我们需要的注解 要想实现对数据库的操作,我们必须知道数据表名以及表中的字段名称以及类型,正如hibernate 使用 ...
- Java基础--注解、反射
一.注解(Annotation) 1.什么是注解? 从JDK5开始,Java增加了Annotation(注解),Annotation是代码里的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行 ...
- java利用注解及反射做通用的入参校验
一.原理: 1.做一个field注解,注解有两个参数:是否必填.toString之后的最大长度 2.对某个request类(或基类),使用注解标记某个字段的校验详情 3.通用的static方法,利用反 ...
- 【Java】利用注解和反射实现一个"低配版"的依赖注入
在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...
- Java利用自定义注解、反射实现简单BaseDao
在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句. 这是整体的目录结构,本来是为复习注解建立的项目^.^ 好的,首先 ...
- Java基础13:反射与注解详解
Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...
随机推荐
- NOIP模拟5 T2
题面:求出满足以下条件的 n*m 的 01 矩阵个数: (1)第 i 行第 1~li 列恰好有 1 个 1 (li+1到ri-1不能放1) (2)第 i 行第 ri~m 列恰好有 1 个 1. ...
- TVM性能评估分析(三)
TVM性能评估分析(三) Figure 1. TVM's WebGPU backend close to native GPU performance when deploying models to ...
- Tensor基础实践
Tensor基础实践 飞桨(PaddlePaddle,以下简称Paddle)和其他深度学习框架一样,使用Tensor来表示数据,在神经网络中传递的数据均为Tensor. Tensor可以将其理解为多维 ...
- CUDA Pro:通过向量化内存访问提高性能
CUDA Pro:通过向量化内存访问提高性能 许多CUDA内核受带宽限制,而新硬件中触发器与带宽的比率不断提高,导致带宽受限制的内核更多.这使得采取措施减轻代码中的带宽瓶颈非常重要.本文将展示如何在C ...
- vue中dom节点转图片
今天项目中有个需求,需要将页面的一部分转为图片,相当于存证之类的 然后我查阅了下百度,发现了几种可行的方法,特此来记录下 1.html2canvas插件 安装:npm install --save h ...
- 基于SKLearn的SVM模型垃圾邮件分类——代码实现及优化
一. 前言 由于最近有一个邮件分类的工作需要完成,研究了一下基于SVM的垃圾邮件分类模型.参照这位作者的思路(https://blog.csdn.net/qq_40186809/article/det ...
- Python跨域问题解决集合
Flask 安装插件 pip install flask-cors 使用 CORS函数配置全局路由 from flask_cors import * app = Flask(__name__) COR ...
- Task00:绪论 - 环境搭建
本章重点: 在电脑上安装MySQL数据库系统 安装客户端并连接到本机上的MySQL数据库 使用提供的脚本创建本教程所使用的示例数据库 1. MySQL 8.0 的安装 考虑到大家所使用的操作系统的不同 ...
- Redis不是只有get set那么简单
我以前还没接触Redis的时候,听到大数据组的小伙伴在讨论Redis,觉得这东西好高端,要是哪天我们组也可以使用下Redis就好了,好长一段时间后,我们项目中终于引入了Redis这个技术,我用了几下, ...
- Java代码优化:使用构造函数和使用一个个setter的效率差别
在对Java代码进行优化的时候,想方设法的要提高整体的效率,使用JProfiler看代码的时间占比,然后,看看哪些部分是可以优化的,减少运行时间的.下面有这么几个方向. 1. 能使用构造函数一步到位的 ...