进阶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里面可以根据类加载器而后进行指 ...
随机推荐
- MAC下STF安装及踩坑
[Mac OS X]brew: command not found ruby -e"$(curl -fsSL https://raw.githubusercontent.com/Homebr ...
- java代理浅述
代理 代理主要可以分为: 静态代理 JDK自带的动态代理 Cglib 静态代理 静态代理比较简单,简单来说就是不想直接调用被代理类,通过代理类来实现功能.如下就是使用了静态代理 定义接口 public ...
- [JDBC]批量提交插入语句以提高数据插入速度(效率提升不明显)
// Initialize conn&stmt Connection conn=null; Statement stmt=null; ... conn=dataSource.getConnec ...
- [MySql]MySql中外键设置 以及Java/MyBatis程序对存在外键关联无法删除的规避
在MySql设定两张表,其中product表的主键设定成orderTb表的外键,具体如下: 产品表: create table product(id INT(11) PRIMARY KEY,name ...
- highcharts 代码都对,但是不显示图片
$('#container').highcharts({ chart: { zoomType: 'xy' }, title: { text: 'Average Monthly Temperature ...
- 通过一个name获取tbody下的其他name的值
<tbody id="add_enterGoods_table"> <tr> <td align="center">< ...
- 为什么单个TCP连接很难占满带宽
计算 TCP吞吐量的公式 TCP窗口大小(bits) / 延迟(秒) = 每秒吞吐量(bits) 比如说windows系统一般的窗口大小为64K, 中国到美国的网络延迟为150ms. 64KB = 6 ...
- centos7搭建伪分布式集群
centos7搭建伪分布式集群 需要 centos7虚拟机一台: jdk-linux安装包一个 hadoop-2.x安装包1个(推荐2.7.x) 一.设置虚拟机网络为静态IP(最好设成静态,为之后编程 ...
- 《Java语言程序设计》第三讲类与对象“动手动脑”
一.以下代码为何无法通过编译?哪儿出错了? 答: 如果类提供了一个自定义的构造方法,将导致系统不再提供默认构造方法. 二. (1)以下代码输出结果是什么? package xy; public cla ...
- eclipse 建立Maven java工程
1.在项目资源管理器右键---新建---项目 2.在选择向导里选择Maven---Maven Project 3.选择默认的工作空间,下一步 4.选择箭头所示选项 5.输入组织名和工程名.点击完成