java的注解
1.注解的含义
注解和接口与类一样,都属于数据类型。
2.注解的作用
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 编写文档
* @author wf
*
*/
//代码分析(做配置)
@WebServlet("/t1")
public class t1 extends HttpServlet {
//编译检查:
@Override
public String toString() {
return "t1 []";
}
/*
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}*/
}
1.编译检查:通过代码中标识的注解,让编译器实现基本的编译检查。如:@Override
2.代码分析(做配置):通过注解,对代码分析,取代xml的作用
3.编写文档:通过注解生成帮助文档
3.注解的特点
1.注解可以在变量,方法与类上加载
2.注解可以有属性,也可以不包含属性 @Override @Text(timeout=1000)
3.注解的作用范围(a.源码 b.编译期间 c.运行期间)
a.源码期间有效:String类上的@Author @Since @See
作用:使命令javadoc将当前的源码生成帮助文档,可识别String上的相关注解
b.编译期间有效:@Override @Deprecated @Suppresswaming
作用:告诉编译器部分信息
c.运行期间有效:@Text
作用:当我们再当前代码上以Junit方式运行时,Junit会运行方法上包含@Test注解的方法
//注释含义:如果执行时长超过1s就报错
@Test(timeout=1000)
public static void tset03() {
}
4.jdk提供的3种注解
@Override @Deprecated @Suppresswarning
public class a1 {
//注解含义:声明当前方法是重写的父类方法
@Override
public String toString() {
return super.toString();
}
public static void name() {
//以下注解的含义是:抑制编译器发生警告信息
@SuppressWarnings(value = { "unused" })
int a;
@SuppressWarnings("unused")
int i;
//以下注解的含义是:抑制编译器发生警告信息(如果有变量未使用,未遵循泛型格式错误不报警告)
@SuppressWarnings(value = {"unused","rawtypes"})
List list = new ArrayList();
}
//注解含义:说明当前的方法已过时,不建议使用
@Deprecated
public static void name1() {
System.out.println("fqegf");
}
}
5.自定义注解
格式
public @interface 注解名称{
public 属性类型 属性名称1();
public 属性类型 属性名称2() default 默认值;
}
import java.util.Date;
public @interface myAnno {
//定义一个变量
public int a();
//定义一个变量,设置其默认值为-1
public long timeout() default -1;
//支持类型的一维数组
public String[] strs();
//报错:原因:属性不支持自定义类类型
//public Date date();
}
自定义注解中成员变量支持的类型
基本数据类型(4类8种),String, Class ,Annotation(注解类型),枚举类型,及以上类型的一维数组类型
框架:一大堆工具类组合,目的:加速项目开发
后期的学习中,框架部分hibernate,spring,struts2很多信息需要配置,提供了2种形式配置 (xml,注解)
什么时候用注解来做配置?
如果配置信息不会发生修改,如:servlet的路径,建议使用注解做配置
如果配置信息需要发生频繁的修改,如:用户的姓名和密码,采用传统方式配置(.txt .xml .properties)
<students>
<stu>
<stuNum>s002</stuNun>
<stuPhone>
<stuHomePhone>124324</stuHomePhone>
<stuCmpPhone>12342143</stuCmpPhone>
</stuPhone>
</stu>
</students>
测试自定义注解
1_自定义注解@MyTest
通过元注解@Rentention @Target声明当前注解作用域以及目标对象,如果没有声明,在运行期间是无法获取到注解的信息
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//自定义注解,相当于JUnit@Test
//定义注解的时候,需要通过元注解Retention说明当前自定义注解的作用域(Class,Source,Runtime)
@Retention(RetentionPolicy.RUNTIME)
//定义注解的时候,需要通过元注解Target说明当前的自定义注解的目标对象
@Target(ElementType.METHOD)
public @interface MyAnno {
//在MyTest注解中定义成员属性,默认值为-1
public int a() default 1;
}
2_定义UserDao
创建4个方法addUser delUser uptUser getUser ,在前三个方法上加载注解
public class Userdao {
static{
System.out.println("加载静态代码段的消息");
}
@MyAnno
public void addUser(){
System.out.println("增加用户");
}
@MyAnno
public void delUser(){
System.out.println("删除用户");
}
@MyAnno
public void uptUser(){
System.out.println("更新用户");
}
public void getUser(){
System.out.println("获取用户");
}
}
3_定义类MyJunit ,模拟JUnit
将UserDao.class文件加载到内存,
获取到字节码文件上所有的方法
遍历方法,判断每个方法上是否加载了@MyTest注解
如果当前方法上设置@MyTest,执行当前的方法
import java.lang.reflect.Method;
public class Myjunit {
public static void main(String[] args) throws Exception {
//加载UserDao.class字节码文件中的方法,判断哪些方法上有自定义的注解@MyTest,如果当前的方法有@MyTest,执行,否则不执行
//1_将UserDao.class字节码文件加载到内存中 ,class对象(代表字节码文件在内存中的对象)
Class c1 = Class.forName("testAnno.Userdao");
Class c2 = Userdao.class;
Userdao u = new Userdao();
Class c3 = u.getClass();
//2_获取字节码对象上所有的方法,返回Method数组对象,数组中的每一个元素都代表Method对象(相当于字节码上的每一个方法)
Method[] mds = c1.getMethods();
//3_遍历字节码对象上所有的方法
for (Method md : mds) {
//测试方法的名称
System.out.println(md.getName());
//判断当前方法上是否有@MyTest注解信息
//md.invoke(new UserDao());
System.out.println(md.isAnnotationPresent(MyAnno.class));
if(md.isAnnotationPresent(MyAnno.class)){
//如果当前的方法上有@MyTest注解,执行,否则忽略
md.invoke(new Userdao());
}
}
}
}
注:通过反射来读取字节码上的注解信息。md.isAnnotationPresent(MyTest.class)"