进阶Java编程(13)反射与Annotation
1,反射取得Annotation信息
从JDK1.5之后Java提供了Annotation技术支持,这种技术为项目的编写带来了新的模型,而后经过了十年的发展,Annotation的技术得到了非常广泛的应用,并且已经在所有的项目开发之中都会存在。
获取Annotation信息
在进行类或方法定义的时候都可以使用一系列的Annotation进行声明,如果要想获取这些Annotation的信息,那么就可以直接通过反射来完成。在java.lang.reflect里面有一个AccessibleObject类,在本类中提供有获取Annotation类的方法:
①获取全部Annotation:public Annotation[] getAnnotations()
②获取指定Annotation:public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
·范例:定义一个接口,并且在接口上使用Annotation
package com.mufasa.demo1; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; public class JavaAPIDemo {
public static void main(String[] args) throws NoSuchMethodException {
{//获取接口上的Annotation信息
Annotation[] annotations=IMessage.class.getAnnotations();
for(Annotation temp:annotations){
System.out.println(temp);
}
}
System.out.println("-------");
{//①获取MessageImpl子类上的Annotation,失败;②获取MessageImpl.toString方法
Method method=MessageImpl.class.getDeclaredMethod("send", String.class);
Annotation[] annotations=method.getAnnotations();
for(Annotation temp:annotations){
System.out.println(temp);
}
}
}
}
package com.mufasa.demo1;
/*
什么是函数式接口(Functional Interface)
其实之前在讲Lambda表达式的时候提到过,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。
这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
函数式接口用途
它们主要用在Lambda表达式和方法引用(实际上也可认为是Lambda表达式)上。
*/
@FunctionalInterface
@Deprecated(since = "1.5")
interface IMessage {//现在这里有两个Annotation
public void send(String msg);
}
package com.mufasa.demo1; import java.io.Serializable; @SuppressWarnings("serial")//无法在程序执行的时候获取
public class MessageImpl implements IMessage, Serializable {
@Override
public void send(String msg) {
System.out.println("【消息发送】"+msg);
}
}
不同的Annotation有它存在的范围,下面对比两个Annotation:
现在发现【@FunctionalInterface】是在运行时生效的Annotation,所以当程序执行的时候可以获取此Annotation,而【@SuppressWarnings】是在源代码编写的时候有效。而在【RetentionPolicy】枚举类中还有一个class的定义,指的是类定义的时候生效。
2,自定义Annotation
现在已经清楚了Annotation的获取,以及Annotation的运行策略,但是最为关键性的一个因素是如何可以实现自定义的Annotation呢?为此在Java里面提供有新的语法,使用【@interface】来定义Annotation。
·范例:自定义Annotation
package com.mufasa.demo2; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME)//定义Annotation的运行策略
@interface DefaultAnnotation {//自定义Annotation
public String title();//获取数据
public String url() default "www.cnblogs.com";//获取数据,默认值
}
package com.mufasa.demo2; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class JavaAPIDemo {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Method method=Message.class.getMethod("send", String.class);//获取指定方法
DefaultAnnotation annotation=method.getAnnotation(DefaultAnnotation.class);//获取指定Annotation
// System.out.println(annotation.title());
// System.out.println(annotation.url());
String msg=annotation.title()+"("+annotation.url()+")";//消息内容
method.invoke(Message.class.getDeclaredConstructor().newInstance(),msg);
}
}
使用Annotation之后最大的特点就是可以结合反射机制实现程序的处理。
3,工厂设计模式与Annotation整合
现在已经清楚Annotation的整体作用,但是Annotation在开发之中能做哪些事情呢?为了帮助大家进一步理解Annotation的处理目的下面将结合工厂设计模式来应用Annotation操作。
package com.mufasa.demo3; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME)
public @interface UseMessage {
public Class<?> clazz();
}
package com.mufasa.demo3; @UseMessage(clazz = MessageImpl.class)//!!!通过注解来控制整个程序的完成!!!
public class MessageService {
private IMessage message;
public MessageService(){
UseMessage useMessage=MessageService.class.getAnnotation(UseMessage.class);
this.message=(IMessage) Factory.getInstance(useMessage.clazz());
}
public void send(String msg){
this.message.send(msg);
}
}
package com.mufasa.demo3; public class JavaAPIDemo {
public static void main(String[] args){
//①普通
// IMessage msg=Factory.getInstance(MessageImpl.class);
// msg.send("www.cnblogs.com");
//②特殊
MessageService messageService=new MessageService();
messageService.send("www.cnblogs.com");
}
}
/*
【代理连接】进行消息发送通道的连接
【消息发送】www.cnblogs.com
【代理断开】关闭连接通道
*/
package com.mufasa.demo3; import java.lang.reflect.InvocationTargetException; class Factory {
private Factory(){}
public static <T> T getInstance(Class<T> clazz){//直接返回实例化操作对象
try{
return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance());
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
由于Annotation的存在,所以对于面向接口的编程的配置处理将可以直接利用Annotation的属性完成控制,从而使得整体代码变得简洁。
进阶Java编程(13)反射与Annotation的更多相关文章
- 进阶Java编程(10)反射与简单Java类
1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...
- 进阶Java编程(9)反射与类操作
1,反射获取类结构信息 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口).包.属性.方法(构造方法与普通方法). ...
- 进阶Java编程(8)反射应用案例
1,反射实例化对象 经过一系列分析之后可以发现虽然获得了Class类的实例化对象但是依然觉得这个对象获取的意义不是很大,所以为了进一步的帮助大家理解反射的核心意义所在,下面将通过几个案例进行说明(都是 ...
- 进阶Java编程(7)反射机制
反射机制 1,反射机制简介 在Java语言里面之所以会有如此多的开源技术支撑,很大的一部分是来自于Java最大的特征[反射机制].如果你不能够使用反射机制去进行项目的开发与设计,那么可以说你并未接触到 ...
- Java编程之反射中的注解详解
"注解"这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题.我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些"注解&quo ...
- 黑马程序员:Java编程_反射技术
=========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性 ...
- JAVA编程之——反射Reflect
说到反射,首先要说一下Java中的类和对象. 在Java中万事万物皆对象(有两个 例外,一个是普通数据类型,另一个是静态的东西,静态的东西不是对象的,是属于类的). 在Java中,类也是对象,类是ja ...
- Java编程基础-反射
一.java反射 1.反射:动态获取类的信息,以及动态调用对象的方法的功能.可以理解为动态看透类的能力. 2.主要功能:在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意 ...
- 进阶Java编程(11)ClassLoader类加载器【待完成】
1,ClassLoader类加载器简介 在Java里面提供一个系统的环境变量:ClassPath,这个属性的作用主要是在JVM进程启动的时候进行类加载路径的定义,在JVM里面可以根据类加载器而后进行指 ...
随机推荐
- Nginx之搭建反向代理实现tomcat分布式集群
参考博文: Nginx反向代理实现Tomcat分布式集群 1. jdk 安装 jdk 下载网址: http://www.oracle.com/technetwork/java/javase/downl ...
- 删除Linux系统多余的引导
问题: 电脑中安装了多个Linux系统,需要删除不用的Linux系统的引导 解决方法: open terminal: su - 切换root用户 cd /boot/ ls ... grub ...
- postgreSQL计算总数sum if case when
假设postgreSQL中表名为user,现在需要计算每个用户参加过的次数(is_join字段为null时不算,表中的null并不是字符串''或者字符串'Null' ,而是数据库中的null类型) u ...
- 2965 -- The Pilots Brothers' refrigerator
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 27893 ...
- java不用中间变量交换两个值
public void changeVal(){ int a = 2; int b = 3; System.out.println("交换前 a:"+a+",b:&quo ...
- linux服务之memcached
http://www.runoob.com/memcached/memcached-cas.html https://github.com/memcached/memcached/blob/maste ...
- Linux 上svn使用http访问设置
https://blog.csdn.net/wobuxingfang/article/details/70835414https://blog.csdn.net/u010487568/article/ ...
- 手机通过fiddler调试页面
fiddler设置 首先我们打开Fiddler->Tools->Fiddler Options在Connection面板里将Allow remote computers to connec ...
- XmlEncrypt
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- k8s 1.15.2 部署
目录 一.环境准备 二.软件安装 三.部署master节点 四.部署node节点 五.集群状态检测 一.环境准备 IP地址 节点角色 CPU Memory Hostname Docker versio ...