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

一、注解

注解(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());

 }
}

总结

到此这篇关于Java中的注解和反射的文章就介绍到这了,更多相关Java注解和反射内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java注解与反射原理说明

    一 点睛 注解若想发挥更大作用,还需借助反射机制之力.通过反射,可以取得一个方法上声明的注解的全部内容. 一般有两种需求: 1 取得方法中全部的注解,通过调用getAnnotations来实现. 2 判断操作是否是指定注解,通过调用getAnnotation来实现. 下面从源码角度来说明怎样获取这些注解信息. 二 源码导读--取得方法中全部的注解 public class AccessibleObject implements AnnotatedElement { ... //取得全部Annot

  • Java 自定义注解及利用反射读取注解的实例

    一.自定义注解 元注解: @interface注解: 定义注解接口 @Target注解: 用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败.如:ElementType.METHOD,ElementType.TYPE: @Retention 注解:用于约束被定义注解的作用范围,作用范围有三个: 1.RetentionPolicy.SOURCE:作用范围是源码,作用于Java文件中,当执行javac时去除该注解. 2.RetentionPolicy.CLASS:作用范围是二进制码

  • java 注解annotation的使用以及反射如何获取注解

     一.注解基本知识 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口. 2. 参数成员只能用public或默认(default)这两个访问权修饰 3. 参数成员只能用基本类型byte,short,char,int,long,float,doubl

  • Java利用反射如何查找使用指定注解的类详解

    前言 最近有些空,想自己写个跟spring里的注解一样的注解来用,然后希望能找到使用了自己写了注解的类,下面来介绍一下实现方法 声明,下面代码是没看过spring源码写的,基本上都是网上找的博客,整理的 定义注解 Controller.java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Controller { } RequestMapping.jav

  • 浅谈Java自定义注解和运行时靠反射获取注解

    java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能. 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annotation 包中. 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1.1.@Retention: 定义注解的保留策略 @Retention(RetentionPolicy.SOURCE) //注解仅

  • Java利用自定义注解、反射实现简单BaseDao实例

    在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句. 这是整体的目录结构,本来是为复习注解建立的项目^.^ 好的,首先我们来确定思路. 1. 自定义@Table @Column注解, 我们稍微模仿hibernate,让@Table作用于类上,来表明实体类与数据表的映射关系,且让@Table中的属性value映射为数据表的名称tableName:让@Column作用于属性上(这里没实现作用于set方法上),表明属性与

  • Java通过反射访问注解信息的方法示例

    本文实例讲述了Java通过反射访问注解信息的方法.分享给大家供大家参考,具体如下: 一 点睛 利用Java的反射机制,可以访问注解信息.比如在调用某个方法时,需要知道该方法的一些基本信息,而这些信息又需要动态获取时,利用发射获取注解信息是一个比较理想的处理方式. 二 实战--访问类的某个成员方法的注解信息 1 代码 import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java

  • 浅谈java反射和自定义注解的综合应用实例

    前言 前几天学习了反射和自定义注解,刚好工作中遇到一个小问题:前台传递到后台的必填字段为空,导致不能插入数据库.就是这样一个小问题,让我考虑到是否可以做一个通用的方法,让前台传递过来的必填字段在后台也校验一遍,如果传递为空,则把响应字段返回提示.因此,我考虑的是用注解的方式,在必填字段上面定义,利用反射得到必填字段的字段名,判断是否为空,并返回响应的信息. 需求模拟 假设客户有:姓名,年龄,地址,手机号码,身份证号等信息,而我们是做金融业务,所以关键是看客户的三要素:姓名,身份证号,手机号码.我

  • java基础之反射和泛型以及注解

     java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型,不能为基本类型. 实现公用的类和方法,对公用的业务进行抽取. 泛型方法/泛型类/泛型接口 public class GenericTest { /** * 泛型声明,定义泛型方法 * @param <T> * @param <K> * @param t * @param k */ p

  • Java基于反射机制实现全部注解获取的方法示例

    本文实例讲述了Java基于反射机制实现全部注解获取的方法.分享给大家供大家参考,具体如下: 一 代码 class Info{ //给mytoString方法加了2个内建Annotation @Deprecated @SuppressWarnings(value = "This is a waring!") public String mytoString(){ return "hello world"; } } class GetAnnotations{ publi

随机推荐