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());
}
}

输出结果:

Java中的注解和反射实例详解

结论:三种方式获取的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

标签:java,注解,反射
0
投稿

猜你喜欢

  • java web手写实现分页功能

    2022-02-04 02:23:15
  • C++中用指向数组的指针作函数参数

    2022-08-27 23:11:33
  • Mybatis中and和循环or混用操作(or转换成in)

    2023-09-19 11:08:34
  • Android中TelephonyManager类的方法实例分析

    2021-07-29 10:35:28
  • Android开发时尽管已root但是ddms还是没有data路径怎么办

    2023-01-28 03:19:36
  • 详解springboot springsecuroty中的注销和权限控制问题

    2023-04-05 15:09:51
  • java Unicode和UTF-8之间转换实例

    2023-04-05 01:56:00
  • Java 实战项目锤炼之网上商城系统的实现流程

    2022-06-26 17:21:47
  • java子类调用父类的方法中包含子类重写的实例方法

    2023-12-22 21:14:50
  • Java调用wsdl接口的两种方法(axis和wsimport)

    2023-06-23 14:41:22
  • dialog dismiss时键盘不消失的问题浅析及解决办法

    2021-09-18 10:06:30
  • Spring Security添加验证码的两种方式小结

    2021-08-05 17:24:25
  • java查找图中两点之间所有路径

    2022-10-04 03:08:11
  • c#网络唤醒功能实现

    2022-07-03 03:26:51
  • Java传入用户名和密码并自动提交表单实现登录到其他系统的实例代码

    2023-09-20 00:40:46
  • 基于WPF实现简单放大镜效果

    2022-02-15 23:19:12
  • 解析Spring事件发布与监听机制

    2022-09-01 09:52:19
  • springboot如何静态加载@configurationProperties

    2021-12-13 16:20:13
  • 初识Spring Boot框架之Spring Boot的自动配置

    2022-08-25 10:27:57
  • Java卡片布局管理器解释及实例

    2022-03-12 18:26:19
  • asp之家 软件编程 m.aspxhome.com