Annotation注解
元注解:
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
@Target:
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention:
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
Override注解表示子类要重写(override)父类的对应方法
Deprecated注解表示方法是不建议被使用的
Suppress Warnings注解表示抑制警告
//使用@interface来声明一个注解(实际上是自动继承了java.lang.annotation.Annotation接口)
//@Target(ElementType.METHOD) //这个注解只能标注在method的方法上
public @interface AnnotationTest {
String value1() default "hello"; //String类型的 使用defalut设置默认值
EnumTest value2(); //枚举类型
String[] value3(); //数组类型
}
/*如果注解里只定义了一个属性,名字是value,那么可以直接赋值,不需要使用name=value这种赋值方式*/
/*
public @interface AnnotationTest {
String value();
}
@AnnotationTest("test")
public void method(){
System.out.println("usage of Annotation");
}
但是我还是对自定义的注解有啥用没啥感觉
*/
public enum EnumTest {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
@Retention(RetentionPolicy.RUNTIME) //Runtime级别的,表示运行时有效
public @interface MyAnnotation {
String hello() default "hello,chicago";
String world();
}
@Retention(RetentionPolicy.CLASS) //在class文件中有效
public @interface MyAnnotation2 {
String hello() default "hello";
}
public class Test {
@SuppressWarnings("unchecked")
@Deprecated
@MyAnnotation2(hello="I'm not here")
@MyAnnotation(world="world",hello="not default")
public void TestMethod(){
System.out.println("this is a method");
}
public static void main(String[] args) throws Exception {
Test test=new Test();
Class<Test> c=Test.class;
Method method=c.getMethod("TestMethod", new Class[]{});
//AnnotatedElement接口中的方法isAnnotationPresent(),判断传入的注解类型是否存在
if(method.isAnnotationPresent(MyAnnotation.class)){
method.invoke(test, new Object[]{});
//AnnotatedElement接口中的方法getAnnotation(),获取传入注解类型的注解
MyAnnotation myAnnotation=method.getAnnotation(MyAnnotation.class);
String hello=myAnnotation.hello();
String world=myAnnotation.world();
System.out.println("hello:"+hello+"\t world:"+world);
}
System.out.println("------------------------------------------------------");
//@Retention(RetentionPolicy.RUNTIME)只有Runtime级别才能被反射读取出来
Annotation[] annotations=method.getAnnotations();
for (Annotation a:annotations) {
System.out.println(a.annotationType().getName());
}
}
}
/**
* @MyAnnotation @MyAnnotation2 @Deprecated @SuppressWarnings
* 四个注解,俩个自己写的,一个级别为RUNTIME,一个为CLASS 另外俩个系统的不知道
* 使用反射来获取MyAnnotation中的属性的值
* 获取Retation级别为Runtime的注解
*/
public class Calculate {
public int add(int a,int b){
return a+b;
}
public int divide(int a,int b) throws Exception{
if(0==b){
throw new Exception("除数不能为0");
}
return a/b;
}
}
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class CalulateTest {
private Calculate calculate;
@Before
public void before()throws Exception{
calculate=new Calculate();
System.out.println("----------before()----------------");
}
@After
public void after()throws Exception{
System.out.println("----------after()----------------");
}
@Test
public void addTest()throws Exception{
System.out.println("do add test");
int result=calculate.add(12, 2);
assertEquals(14,result);
}
@Test(expected=Exception.class)
public void div() throws Exception{
System.out.println("do divide test");
calculate.divide(8, 0);
}
}
do add test
----------after()----------------
----------before()----------------
do divide test
----------after()----------------
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface After {}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
Class<? extends Object> expected() default String.class;
}
public class Calculate {
public int add(int a,int b){
return a+b;
}
public int divide(int a,int b) throws Exception{
if(0==b){
throw new Exception("除数不能为0");
}
return a/b;
}
}
import day104_reflect_JunitAnnotation2.Calculate;
import static day104_reflect_JunitAnnotation2.MyJUnit.*;
public class MyCalulateTest {
private Calculate calculate;
@Before
public void before()throws Exception{
calculate=new Calculate();
System.out.println("----------before()----------------");
}
@After
public void after()throws Exception{
System.out.println("----------after()----------------");
}
@Test
public void addTest()throws Exception{
System.out.println("do add test");
int result=calculate.add(12, 2);
assertEquals(14,result);
}
@Test
public void div() throws Exception{
System.out.println("do divide test");
calculate.divide(8, 0); //这里肯定会抛出异常
}
}
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class MyJUnit {
private List<Method> beforeMethod;
private List<Method> afterMethod;
private List<Method> testMethod;
private static List<Exception> exceptions;
private Object object;
private Class<?> testClass;
/**
* 构造方法初始化,获取三个方法集合
*
* @param testName
*/
public MyJUnit(String testName) {
super();
try {
beforeMethod = new ArrayList<Method>();
afterMethod = new ArrayList<Method>();
testMethod = new ArrayList<Method>();
exceptions = new ArrayList<Exception>();
testClass = Class.forName(testName);
object = testClass.newInstance();
getAllMethods();
} catch (Exception e) {
e.printStackTrace();
}
}
private void getAllMethods() {
Method[] method = testClass.getMethods();
for (Method m : method) {
if (m.isAnnotationPresent(Before.class)) {
beforeMethod.add(m);
}
if (m.isAnnotationPresent(After.class)) {
afterMethod.add(m);
}
if (m.isAnnotationPresent(Test.class)) {
testMethod.add(m);
}
}
}
/**
*
*/
public void run() {
for (Method m : testMethod) {
runTest(m);
}
if (exceptions.size() == 0) {
System.out.println("通过测试");
} else {
for (Exception e : exceptions) {
System.out.println("测试不通过,错误为");
e.printStackTrace();
}
}
}
private void runTest(Method m) {
try {
runBefores(); // 先运行before
runTestMethod(m);
runAfters(); // 最后运行after
} catch (Exception e) {
e.getMessage();
throw new RuntimeException(
"test should never throw an exception to this level");
}
}
private void runBefores() throws Exception {
for (Method m : beforeMethod) {
m.invoke(object, new Object[] {});
}
}
private void runAfters() throws Exception {
for (Method m : afterMethod) {
m.invoke(object, new Object[] {});
}
}
/*
* 运行方法,如果有异常,则添加异常进入exceptions集合中去
*/
private void runTestMethod(Method m) throws Exception {
try {
Test testAnnotation = m.getAnnotation(Test.class);
m.invoke(object);
} catch (Exception e) { // 如果测试不通过
addExceptions(e);
}
}
private static void addExceptions(Exception e) {
exceptions.add(e);
}
static public void assertEquals(Object obj, Object actual) {
if (obj.equals(actual)) {
return;
} else {
addExceptions(new Exception("预期值与实际值不相等"));
}
}
}
public class TestFinal {
public static void main(String[] args) {
MyJUnit myJUnit=new MyJUnit("day104_reflect_JunitAnnotation2.MyCalulateTest");
myJUnit.run();
}
}
do add test
----------after()----------------
----------before()----------------
do divide test
----------after()----------------
测试不通过,错误为
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at day104_reflect_JunitAnnotation2.MyJUnit.runTestMethod(MyJUnit.java:106)
at day104_reflect_JunitAnnotation2.MyJUnit.runTest(MyJUnit.java:76)
at day104_reflect_JunitAnnotation2.MyJUnit.run(MyJUnit.java:61)
at day104_reflect_JunitAnnotation2.TestFinal.main(TestFinal.java:7)
Caused by: java.lang.Exception: 除数不能为0
at day104_reflect_JunitAnnotation2.Calculate.divide(Calculate.java:10)
at day104_reflect_JunitAnnotation2.MyCalulateTest.div(MyCalulateTest.java:31)
... 8 more