【JAVA基础篇】注解

一、什么是注解?

注解是元数据,所谓元数据就是描述数据的数据。

在annotation诞生之前(jdk1.5诞生了注解),甚至之后,xml被广泛的由于描述元数据。但是后来,有一些应用开发工程师和架构师觉得它越来越难以维护了,他们觉得需要一种和代码紧耦合的东西,而不是xml配置和代码是松耦合的(某些情况下甚至是完全分离的),于是annotation诞生了。

假如你想为应用设置很多的常量或参数,这种情况下,XML是一个很好的选择,因为它不会同特定的代码相连。如果你想把某个方法声明为服务,那么使用Annotation会更好一些,因为这种情况下需要注解和方法紧密耦合起来,开发人员也必须认识到这点。

目前,许多框架将XML和Annotation两种方式结合使用,平衡两者之间的利弊。

二、使用注解的好处

  1. 对代码进行标记
  2. 生成文档
  3. 编译时进行语法检查
  4. 减少XML配置

三、注解的分类

3.1、元注解

用来定义注解的注解,@interface、@Target、@Retention、@Inherited

注解作用
@interface定义注解
@Target声明注解的使用目标,说明这个可以在类型上使用,还是属性、还是方法、还是参数
@Retention注解应该如何去保留,是在源码中保留,还是在字节码文件中保留,还是在运行时保留
@Inherited子类是否继承父类在类上定义的注解

3.2、内置注解

jdk定义的一些注解,还有很多其他的,这里只列举一部分:@SuppressWarnings、@Deprecated、@Override、@Documented、@FunctionaInterface、@SafeVarargs、@version、@author、@param、@exception、@return

@SuppressWarnings忽略警告
@Deprecated弃用
@Override说明此方法重写父类的方法
@Documented生成javadoc,生成javadoc时默认是不生成注解说明的,但是如果使用了@Documented来定义这个注解,那么将会生成注解说明

3.3、自定义注解

使用@interface来自定义一个注解

四、注解使用示例

我们先来定义几个注解

4.1、注解定义

package org.cc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
	String value();
}
package org.cc.annotation;

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;

@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
	String value();
}
package org.cc.annotation;

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;

@Inherited
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Parameter {
	String value() default "";
}
package org.cc.annotation;

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;

@Inherited
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
	String value() default "root";
}
package org.cc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Required {
}

4.2、使用注解

package org.cc.annotation.use;

import org.cc.annotation.Controller;
import org.cc.annotation.Inject;
import org.cc.annotation.Parameter;
import org.cc.annotation.Permission;
import org.cc.annotation.Required;
/**
 * 定义一个类,来使用刚刚定义的注解
 * @author cc
 *
 */
@Controller("testController")
public class TestController {
	@Inject("injectStr")
	private String injectStr;
	
	@Permission("testPermission")
	public void test(@Parameter("param") @Required String param,String param2){
		
	}
}
package org.cc.annotation.use;

/**
 * TestController类的子类
 * @author cc
 *
 */
public class SubTestController extends TestController{
	private String injectStr;
	
	public void test(String param,String param2){
		
	}
}

4.3、解析注解

package org.cc.annotation.use;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import org.cc.annotation.Controller;
import org.cc.annotation.Inject;

/**
 * 使用反射来解析注解
 * @author cc
 *
 */
public class JXAnnotation {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
		
		Class clazz = Class.forName("org.cc.annotation.use.TestController");
		Annotation[] annotations = clazz.getAnnotations();//得到指定类的所有注解
		for (Annotation a: annotations ) {
            System.out.println(a);
        }
		Controller c = (Controller)clazz.getAnnotation(Controller.class);//得到类特定的注解
		System.out.println(c.value());
		
		Field f = clazz.getDeclaredField("injectStr");
		Inject inject = f.getAnnotation(Inject.class);
		System.out.println(inject.value());
		
		Class clazz1 = Class.forName("org.cc.annotation.use.SubTestController");
		Controller c1 = (Controller)clazz1.getAnnotation(Controller.class);//得到类特定的注解
		System.out.println(c1);//因为定义Controller时没有使用Inherited元注解,所以子类SubTestController并不会继承父类的注解Controller
		//注意仅仅针对类,成员属性和方法不受此注释影响,就是说子类方法上的注解一定会继承父类的注解
		
	}

}

五、定义和使用注解需要注意的地方

1、自定义注解我们可以看到有一行String value() ,类似于定义一个方法,这行代码表示使用注解时必须指定value属性值,像这样:@Controller("testController")或者这样写@Controller(value="testController"),不能这样写:@Controller(),编译会报错。如果非要这样使用,那么需要修改这个注解的定义,改成这样String value() default "";或者直接将String value()这一行删掉。

简单描述就是:如果定义注解时定义了value属性,那么使用时必须设置value属性值,或者提供默认的属性值。

2、定义注解时属性是什么类型,那么使用注解时设置的属性值必须跟定义的类型相同。下面这种情况也是可以的:定义时属性值类型为字符串数组,然后使用时设置属性值为字符串。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值