Java中的注解和反射实例详解
作者:说者无心zzz 发布时间:2023-02-02 04:25:45
一、注解
注解(Annotation): 从jdk5.0开始引进,可以对程序进行解释或被其他程序读取。
注解格式:"@注释名",并可以添加一些参数。
例:@MyAnnotation(value=‘value')
1、内置注解
@override: 用于修饰方法,表示该方法声明是重写或实现一个父类的方法
@Deprecated: 用于修饰方法、属性、类,表示已过时不建议使用的
@SuppressWarnings: 用于抑制编译时的警告信息
2、元注解
作用:用于注解其他注解
@Target: 用于描述注解的适用范围
例:@Target(ElementType.ANNOTATION_TYPE) 适用范围为注解定义
@retention: 表示需要在什么级别保存该注解信息
SOURCE - 源码级别
CLASS - class级别
RUNTIME - 运行级别
SOURCE < CLASS < RUNTIME
例:@Retention(RetentionPolicy.RUNTIME) 此注解运行时有效
@Documented: 表示是否将注解生成在Javadoc中
@Inherited: 表示子类可以继承父类的注解
3、自定义注解
注解定义:@interface+注解名
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@interface Myannotation1{
//注解的参数:参数类型 + 参数名();
String Parameter1() ;
int Parameter2() default -1; //默认值为-1代表不存在
}
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.SOURCE )//源码中有效
@interface Myannotation2{
String Value() ;//只有一个参数时,参数名用Value
}
测试:
//有默认值的参数可以不填没有默认值的参数必填,并且参数填写没有顺序
@Myannotation1(Parameter1 = "Parameter1 ")
//参数定义为Value时,前面的"Value = "可以省略
@Myannotation2("Value")
public void test01(){
}
二、反射
反射(Reflection)是java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
优缺点:具有灵活性但是效率较低。
Class c = Class.forName(java.lang.String)
1、Class类
某个类的属性、方法和构造器、某个类实现了哪些接口,JRE都为其保留了一个不变的Class类型的对象,同一个类的所有对象共享同一个Class对象。
Class类具有以下特点:
Class本身也是一个类
Class对象只能由系统建立对象
一个加载的类在JVM中只会有一个Class实例
一个Class对象对应的是一个加载到JVM中的一个class文件
每个类的实例都会记得自己是由哪个Class实例所生成
通过Class可以完整地得到一个类中的所有被加载结构
Class类是Reflection的根源,针对任何想动态加载、运行的类,唯有先获得相应的Class对象
Class类的常用方法:
方法名 | 功能说明 |
---|---|
static Class.forName(String name) | 返回指定类名name的Class对象 |
Object newInstance() | 调用缺省构造函数,返回Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类或void)的名称 |
Class getSuperClass() | 返回当前Class对象的父类Class对象 |
Class[] getinterfaces() | 返回当前Class对象的接口 |
Class Loader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Method getMethod(String name ,Class T) | 返回一个Method对象,此对象的形参类型为paramType |
Field[] getDeclaredFields | 返回Field对象的一个数组 |
2、通过反射获取Class对象:
所有的类都可以通过反射获取其Class对象。
下面通过例子列举获取类的Class对象的三种方式:
//新建Person类
class Person{
String name;
int age;
int id;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//测试
public class test02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Person();
//方式一、通过包名获取
Class class1 = Class.forName("com.reflection.Person");
System.out.println(class1.hashCode());
//方式二、通过对象获取
Class class2 = person.getClass();
System.out.println(class3.hashCode());
//方式三、通过类获取
Class class3 = Person.class;
System.out.println(class3.hashCode());
}
}
输出结果:
结论:三种方式获取的Class对象为同一个。
3、获取类的运行时结构
public class test03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.reflection.Person");
//获得类的名字
String name = c1.getName();//获得包名加类名
String simpleName = c1.getSimpleName();//获得类名
//获得类的属性
Field[] fields = c1.getFields();//获得类的所有公有属性
Field[] declaredFields = c1.getDeclaredFields();//获得类的所有属性
Field field = c1.getField(name);//获得类的指定公有属性
Field declaredField = c1.getDeclaredField(name);//获得类的指定属性(所有类型均可)
//获得类的方法
Method[] method = c1.getMethods();//获得本类及其父类的所有公有方法
Method[] declaredMethods = c1.getDeclaredMethods();//获得本类的所有方法
Method getName = c1.getMethod("getName", null);//获取指定方法(本类及其父类的所有公有方法)
Method setName = c1.getDeclaredMethod("setName", String.class);//获取指定方法(本类的所有方法)
//获得类的构造器
Constructor[] constructors = c1.getConstructors();//获取所有公有构造器
Constructor[] declaredConstructors = c1.getDeclaredConstructors();//获取所有构造器
Constructor constructor = c1.getConstructor(String.class, int.class);//获取指定公有构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);//获取指定构造器
}
}
4、通过反射构造对象
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得Class对象
Class c1 = Class.forName("com.reflection.Person");
//通过反射创建对象
Person person = (Person)c1.newInstance();//本质上是调用了无参构造器
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class);//获取有参构造器
Person person2 = (Person) constructor.newInstance("name",18);//调用有参构造器创建对象
//通过反射调用普通方法
Method setName = c1.getDeclaredMethod("setName", String.class);//获取方法
setName.invoke(person,"name");//通过invoke调用方法
//通过反射操作属性
Field name = c1.getDeclaredField("name");//获取name属性
name.setAccessible(true);//关闭安全检测,关闭后可以访问私有属性(true为关闭,false为打开,默认是false)
name.set(person,"lalala");//设置属性的值
}
}
5、通过反射获取注解的信息
创建类和注解
@Testclass("db_Student2")//类注解
//创建学生类
class Student2{
@Testfield(columnname = "name",type = "varchar",length = 20)//属性注解
String name;
@Testfield(columnname = "age",type = "int",length = 3)
int age;
@Testfield(columnname = "ID",type = "int",length = 10)
int ID;
public Student2() {
}
public Student2(String name, int age, int ID) {
this.name = name;
this.age = age;
this.ID = ID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
}
//类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Testclass{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Testfield{
String columnname();
String type();
int length();
}
测试
public class test05 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.zjrcu.reflection.Student2");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//通过反射获得注解value的值
Testclass testclass = (Testclass)c1.getAnnotation(Testclass.class);
String value = testclass.value();
System.out.println(value);
//获取类中指定注解的value值
Field f = c1.getDeclaredField("name");
Testfield testfield = (Testfield) f.getAnnotation(Testfield.class);
System.out.println(testfield.columnname());
System.out.println(testfield.length());
System.out.println(testfield.type());
}
}
总结
来源:https://blog.csdn.net/qq_39565343/article/details/114263259


猜你喜欢
- 学习编程语言最重要的就是实践。很多小伙伴在学习完编程语言后,一直停留在基础阶段,只懂一大堆理论知识,而不懂得实践。那么,今天我们一起来动手做
- 大致思路:注解实现方式:就是用 反射机制. 获取指定的包下使用了注解的类,存储在一个map容器, 然后获取map容器下类的属性, 利用反射给
- 如果需要处理的数字有许多位,就可以使用BitArray类和BitVector32结构。BitArray类位于System.Collectio
- 今天在于硬件进行交互的过程中,要到了了需要两个数组进行合并,然后对数组进行反转和加密操作,以下是两个byte数组合并的方法。/** *
- Android上杀掉进程的方式有两种,分别是System.exit(0)和Process.killProcess(Process.myPid
- 本文实例为大家分享了java动态导出excel压缩成zip下载的具体代码,供大家参考,具体内容如下package pack.java.io.
- 本文章从头开始介绍Spring集成Redis的示例。Eclipse工程结构如下图为我的示例工程的结构图,采用Maven构建。其中需要集成Sp
- 一般情况下在Word中输入的文字都是横向的,今天给大家分享两种方法来设置/更改一个section内的所有文本的方向及部分文本的方向,有兴趣的
- 一、前言TreeView这个控件对于我来说是用得比较多的,以前做的小聊天软件(好友列表)、音乐播放器(播放列表)、类库展示器(树形类结构)等
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- 本文实例讲述了C#计算矩阵的逆矩阵方法。分享给大家供大家参考。具体如下:1.代码思路1)对矩阵进行合法性检查:矩阵必须为方阵2)计算矩阵行列
- AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合。其实AsyncTask并不是那么好,甚至有些糟糕。本文
- 本文实例讲述了C#实现随机数产生类。分享给大家供大家参考。具体分析如下:这个类主要扩展的random的使用,对一个经常需要使用的随机数生成进
- 1.元组(Tuple)元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的
- Oracle的jdbc驱动三种主要分类:1、JDBC OCI: oci是oracle call interface的缩写,此驱动类似于传统的
- 背景系统: SpringBoot开发的Web应用;ORM: JPA(Hibernate)接口功能简述: 根据实体类ID到数据库中查询实体信息
- 下面代码看下java判断http地址是否连通private boolean isOk(String url) {
- 前言介绍了几篇 Hero 动画,我们来一个 Hero 动画应用案例。在一些应用中,列表的元素和详情的
- spring boot2.x已经出来好一阵了,而且spring cloud 的最新Release版本Finchley.RELEASE,默认集
- 引语:工作中有时候需要在普通的对象中去调用spring管理的对象,但是在普通的java对象直接使用@Autowired或者@Resource