元注解:
元注解的作用就是负责注解其他注解。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); } }
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(); } }