java 中item_JavaSE学习笔记--Item1 注解Annotation

从 JDK 5.0 開始, Java 添加了对元数据(MetaData) 的支持, 也就是 Annotation(注解)。

什么是Annotation,以及注解的作用?

三个主要的 Annotation:

@Override: 限定重写父类方法, 该注解仅仅能用于方法

@Deprecated: 用于表示某个程序元素(类, 方法等)已过时

@SuppressWarnings: 抑制编译器警告.

上面的注解,在我们平时的编程中都是能够看见的。比方定义一个Parent类和一个MyIterface的接口。用Child的子类去继承Parent并实现MyInterface.就能够看到

Parent

public class Parent {

public void m1(){

}

public void l1l1l1l1llll1ll1l1(){

}

}

MyInterface

public interface MyInterface {

void m2();

}

Child

489baa1528594a9b7f405cea797ba790.png

Annotation 事实上就是代码里的特殊标记, 它用于替代配置文件,也就是说。传统方式通过配置文件告诉类怎样执行,有了注解技术后,开发者能够通过注解告诉类怎样执行。在Java技术里注解的典型应用是:能够通过反射技术去得到类里面的注解,以决定怎么去执行类。

掌握注解技术的要点:

怎样定义注解

怎样反射注解。并依据反射的注解信息,决定怎样去执行类

一、注解的基本知识

1、怎样定义注解

定义新的 Annotation 类型使用 @interface 关键字

public @interface 注解的名称{}

2、定义注解中的属性

注解属性的作用:原来写在配置文件里的信息,能够通过注解的属性进行描写叙述。

类型 属性名称() [default 默认值];

Annotation 的属性声明方式:String name();

属性默认值声明方式:String name() default “xxx”;

特殊属性value:假设注解中有一个名称value的属性,那么使用注解时能够省略value=部分,如@MyAnnotation(“xxx"),可是出现多个属性时,那就应该要写上value值,这样比較明白。

定义一个MyAnno1的注解。同一时候定义一个MyAnno2 ,MyAnno2 作为MyAnno1的一个属性。

public @interface MyAnno2 {

int num();

}

//全部定义的注解都是java.lang.annotation.Annotation的子类

//定义注解

public @interface MyAnno1 {

String name() default "";//注解的属性

int age() default 0;

// MyAnno2[] myann(); //属性还能够是注解。注解数组

String [] value() default "";

}

使用自己定义的注解

//使用自己定义的注解

public class UseMyAnno1 {

// @MyAnno1(name = "abc", age = 19, myann = { @MyAnno2(num = 20),

// @MyAnno2(num = 200) }) //myann是一个注解数组。

// public void method() {

//

// }

//@MyAnno1("abc") 就是给注解的value属性赋值

@MyAnno1(value={"def","ddd"},age=10)

public void method() {

}

}

特别注意:类型必须是基本类型、String、Class、注解类型、枚举及以上类型的一维数组。

二、注解的反射

1、 AnnotationElement 接口

JDK 5.0 在 java.lang.reflect 包下新增了 AnnotationElement 接口, 该接口代表程序中能够接受凝视的程序元素,具有例如以下方法

2c2af441bb1de94a56ffa9dfd6e1bcf1.png

T getAnnotation(Class clazz):得到指定的注解类型

Annotation[] getAnnotations():得到全部的注解类型

Annotation[] getDeclaredAnnotations():得到自己上面的直接的注解类型

boolean isAnnotationPresent(Class clazz):有没有指定的注解

Class、Method、Field、Constructor等都实现了该接口。

实例:编写一个自己的注解Anno1,在MyClass1中使用该注解,MyClass2继承MyClass1,这样,MyClass2也具有MyClass1上的注解,可是两者还是有区别的,看例如以下代码

package com.itheima.other.metaanno;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE,ElementType.METHOD})

@Documented

@Inherited

public @interface Anno1 {

}

MyClass1

package com.itheima.other.metaanno;

/**

* 这是一个測试类

*@author wzhting

*

*/

@Anno1

public class MyClass1 {

}

MyClass2

package com.itheima.other.metaanno;

import java.lang.annotation.Annotation;

public class MyClass2 extends MyClass1 {

public static void main(String[] args) {

Class clazz = MyClass2.class;

// Anno1 a1 = (Anno1) clazz.getAnnotation(Anno1.class);

// System.out.println(a1);

Annotation ans[] = clazz.getDeclaredAnnotations();//获取直接存在的注解

for(Annotation a:ans)

System.out.println(a);

}

}

比方:推断Object这个类上面有没有MyAnn1的注解

Class clazz = Object.class;

Boolean b = clazz.isAnnotationPresent(MyAnn1.class);

2、注解的生命周期:

2.1 AnnotatedElement元注解

仅仅能用在注解上的注解,就是元注解。JDK中定义了例如以下元Annotation:

@Retention:

@Retention: 仅仅能用于修饰一个 Annotation 定义, 用于指定该 Annotation 能够保留的域, @Rentention 包括一个 RetentionPolicy 类型的成员变量, 通过这个变量指定域。

RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件里. 当执行 Java 程序时, JVM 不会保留注解. 这是默认值

RetentionPolicy.RUNTIME:编译器将把凝视记录在 class 文件里. 当执行 Java 程序时, JVM 会保留注解. 程序能够通过反射获取该凝视

RetentionPolicy.SOURCE: 编译器直接丢弃这样的策略的凝视

53d7a0d1e6780b4955d977d39dfbecca.png

@Target:指示注解能用在何处

ElementType:指定注解用于修饰类的哪个成员. @Target 包括了一个名为 value。类型为ElementType的成员变量。看源代码可知有TYPE (Class,Interface), FIELD, METHOD, PARAMETER, ANNOTATION_TYPE等声明常量。

实例:自己定义注解类MyTest

首先定义两个实体类,用于单元測试分别为PersonDaoImpl 和測试类PersonDaoImplTest

PersonDaoImpl

package com.itheima.dao.impl;

public class PersonDaoImpl {

public void add(){

System.out.println("保存了");

}

public void del(){

System.out.println("执行了删除");

}

}

PersonDaoImplTest

package com.itheima.dao.impl;

import org.junit.Test;

public class PersonDaoImplTest {

private PersonDaoImpl dao = new PersonDaoImpl();

//測试方法:必须是public的;没有返回值;没有參数

@MyTest(timeout=1)//===>自己编写MyTest注解

public void testAdd() throws InterruptedException{

// Thread.sleep(100);

dao.add();

}

public void testDel(){

dao.del();

}

}

自己定义一个类MyTest,和JUnit的@Test类类似。

package com.itheima.dao.impl;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)//编译时,JVM保留注解

@Target(ElementType.METHOD)//使用于方法。

public @interface MyTest {

long timeout() default -1;//没有时间限制。单位是毫秒

}

反射注解的方法及属性(重点)

通过反射技术,编写MyTestRunner 类,实现MyTest注解的功能。

package com.itheima.dao.impl;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class MyTestRunner {

public static void main(String[] args) throws Exception{

test1();

}

//反射注解的属性

private static void test2() throws IllegalAccessException,

InvocationTargetException, InstantiationException {

Class clazz = PersonDaoImplTest.class;

Method ms[] = clazz.getMethods();

for(Method m:ms){

MyTest myTest = m.getAnnotation(MyTest.class);//假设当前方法上面没有@MyTest注解。返回的是null

if(myTest!=null){

//执行该方法。推断是否超时

long time = System.currentTimeMillis();

m.invoke(clazz.newInstance(), null);

long actualUseTime = System.currentTimeMillis()-time;//实际耗时

//获取注解上配置的timeout属性的值

long planUserTime = myTest.timeout();

if(planUserTime>=0){

//说明用户指定了时间

if(actualUseTime>planUserTime)

throw new RuntimeException("超时");

}

}

}

}

//反射方法上面的注解

private static void test1() throws IllegalAccessException,

InvocationTargetException, InstantiationException {

//得到測试类的字节码

Class clazz = PersonDaoImplTest.class;

//得到全部的方法

Method ms[] = clazz.getMethods();

//推断方法上面有没有叫做@MyTest的注解

for(Method m:ms){

boolean b = m.isAnnotationPresent(MyTest.class);

System.out.println(m.getName()+":"+b);

//假设有:调用该方法

if(b)

m.invoke(clazz.newInstance(), null);

}

}

/* testAdd:true

testDel:false

wait:false

wait:false

wait:false

equals:false

toString:false

hashCode:false

getClass:false

notify:false

notifyAll:false*/

}

下面两个了解就可以。

@Documented:用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.

@Inherited:被它修饰的 Annotation 将具有继承性.假设某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自己主动具有该注解

三、servlet3.0 中的注解

在servlet3.0以后,就能够採用注解的方式代替web.xml文件里的servlet映射了

比方例如以下servlet

package com.itheima.servlet;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Enumeration;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebInitParam;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@WebServlet(value = { "/servlet/ServletDemo1", "/servlet/ServletDemo11" }, initParams = {

@WebInitParam(name = "encoding", value = "UTF-8"),

@WebInitParam(name = "XXX", value = "YYY") })

public class ServletDemo1 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();

out.write("ServletDemo1


");

ServletConfig cfg = getServletConfig();

Enumeration e = cfg.getInitParameterNames();

while(e.hasMoreElements()){

String paramName = (String)e.nextElement();

out.write(paramName+"="+cfg.getInitParameter(paramName)+"
");

}

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

当然,在过滤器和监听器中,也一样能够採用注解的方法代替web.xml的配置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值