Disadvantages of naming patterns

  1. Typographical errors may result in silent failures.
  2. There is no way to ensure that they are used only on appropriate program elements.
  3. They provide no good way to associate parameter values with program elements.

Naming patters example

testXXX

textXXXWithXXXException

Better solution: meta-annotations

// Marker annotation type declaration

import java.lang.annotation.*;

/**

* Indicates that the annotated method is a test method.

* Use only on parameter less static methods.

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Test {

}

/**

* Indicates that the annotated method is a test method that must throw the

* designated exception to succeed.

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface ExceptionTest {

Class<? extends Exception> value();

}

/**

* Annotation type with an array parameter

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface MultiExceptionTest {

Class<? extends Exception>[] value();

}

  1. The @Retention(RetentionPolicy.RUNTIME) meta-annotation indicates that Test annotations should be retained at runtime. Without it, Test annotations would be invisible to the test tool.
  2. The @Target(ElementType.METHOD)meta-annotation indicates that the Test annotation is legal only on method declarations: it cannot be applied to class declarations, field declarations, or other program elements.
  3. The parameter definition Class<? extends Exception> value(); and Class<? extends Exception>[] value(); declare the required one or more exceptions to be generated by the method.

// Program containing marker annotations

public class Sample {

@Test public static void m1() { } // Test should pass

public static void m2() { }

@Test public static void m3() { // Test Should fail

throw new RuntimeException("Boom");

}

public static void m4() { }

@Test public void m5() { } // INVALID USE: nonstatic method

public static void m6() { }

@Test public static void m7() { // Test should fail

throw new RuntimeException("Crash");

}

public static void m8() { }

}

/**

* @author Kaibo

* Program containing annotations with a parameter.

*/

public class Sample2 {

@ExceptionTest(ArithmeticException.class)

public static void m1() { // Test should pass

int i = 0;

i = i / i;

}

@ExceptionTest(ArithmeticException.class)

public static void m2() { // Should fail (wrong exception)

int[] a = new int[0];

int i = a[1];

}

@ExceptionTest(ArithmeticException.class)

public static void m3() {

} // Should fail (no exception)

}

/**

* @author Kaibo

*

*/

public class Sample3 {

// Code containing an annotation with an array parameter

@MultiExceptionTest({ IndexOutOfBoundsException.class,

NullPointerException.class })

public static void doublyBad() {

List<String> list = new ArrayList<String>();

// The spec permits this method to throw either

// IndexOutOfBoundsException or NullPointerException

list.addAll(5, null);

}

}

/**

* @author Kaibo

* Program to process marker annotations.

*/

import java.lang.reflect.*;

public class RunTests {

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

Class<?> testClass = Class.forName(args[0]);

testSample1(testClass);

testClass = Class.forName(args[1]);

testSample2(testClass);

testClass = Class.forName(args[2]);

testSample3(testClass);

}

private static void testSample1(Class<?> testClass) {

int tests = 0;

int passed = 0;

for (Method m : testClass.getDeclaredMethods()) {

if (m.isAnnotationPresent(Test.class)) {

tests++;

try {

m.invoke(null);

passed++;

} catch (InvocationTargetException wrappedExc) {

Throwable exc = wrappedExc.getCause();

System.out.println(m + " failed: " + exc);

} catch (Exception exc) {

System.out.println("INVALID @Test: " + m);

}

}

}

System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed);

}

/**

* @param testClass

*/

private static void testSample2(Class<?> testClass) {

int tests = 0;

int passed = 0;

for (Method m : testClass.getDeclaredMethods()) {

if (m.isAnnotationPresent(ExceptionTest.class)) {

tests++;

try {

m.invoke(null);

System.out.printf("Test %s failed: no exception%n", m);

} catch (InvocationTargetException wrappedEx) {

Throwable exc = wrappedEx.getCause();

Class<? extends Exception> excType = m.getAnnotation(

ExceptionTest.class).value();

if (excType.isInstance(exc)) {

passed++;

} else {

System.out.printf(

"Test %s failed: expected %s, got %s%n", m,

excType.getName(), exc);

}

} catch (Exception exc) {

System.out.println("INVALID @Test: " + m);

}

}

}

System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed);

}

private static void testSample3(Class<?> testClass) {

int tests = 0;

int passed = 0;

for (Method m : testClass.getDeclaredMethods()) {

if (m.isAnnotationPresent(ExceptionTest.class)) {

tests++;

try {

m.invoke(null);

System.out.printf("Test %s failed: no exception%n", m);

} catch (Throwable wrappedExc) {

Throwable exc = wrappedExc.getCause();

Class<? extends Exception>[] excTypes = m.getAnnotation(

MultiExceptionTest.class).value();

int oldPassed = passed;

for (Class<? extends Exception> excType : excTypes) {

if (excType.isInstance(exc)) {

passed++;

break;

}

}

if (passed == oldPassed)

System.out.printf("Test %s failed: %s %n", m, exc);

}

}

}

System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed);

}

}

Summary

There is simply no reason to use naming patterns now that we have annotations. All programmers should, however, use the predefined annotation types provided by the Java platform(Item 36 and Item24).

Effective Java 35 Prefer annotations to naming patterns的更多相关文章

  1. Effective Java 69 Prefer concurrency utilities to wait and notify

    Principle Use the higher-level concurrency utilities instead of wait and notify for easiness. Use Co ...

  2. Effective Java 53 Prefer interfaces to reflection

    Disadvantage of reflection You lose all the benefits of compile-time type checking, including except ...

  3. Effective Java 68 Prefer executors and tasks to threads

    Principle The general mechanism for executing tasks is the executor service. If you think in terms o ...

  4. Effective Java 18 Prefer interfaces to abstract classes

    Feature Interface Abstract class Defining a type that permits multiple implementations Y Y Permitted ...

  5. Effective Java 20 Prefer class hierarchies to tagged classes

    Disadvantage of tagged classes 1. Verbose (each instance has unnecessary irrelevant fields). 2. Erro ...

  6. Effective Java 25 Prefer lists to arrays

    Difference Arrays Lists 1 Covariant Invariant 2 Reified at runtime Erased at run time 3 Runtime type ...

  7. Effective Java 46 Prefer for-each loops to traditional for loops

    Prior to release 1.5, this was the preferred idiom for iterating over a collection: // No longer the ...

  8. Effective Java 49 Prefer primitive types to boxed primitives

    No. Primitives Boxed Primitives 1 Have their own values Have identities distinct from their values 2 ...

  9. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

随机推荐

  1. 十分钟搞懂什么是CGI

    原文:CGI Made Really Easy,在翻译的过程中,我增加了一些我在学习过程中找到的更合适的资料,和自己的一些理解.不能算是严格的翻译文章,应该算是我的看这篇文章的过程的随笔吧. CGI真 ...

  2. C++ async task

    最近在搞Android 开发,里面多线程的使用比较频繁,java多线程接口很方便. Thread, AysncTask, Handler 这些接口比起posix提供的pthread_create()等 ...

  3. 领域实体框架Rafy2 发布了

    在2009年我在codeplex发布了1.0版本OpenExpressApp,下载地址:http://openexpressapp.codeplex.com/.OEA 1.0 作为我十多年开发工作的一 ...

  4. Android 学习笔记之使用多线程实现断点下载...

    PS:莫名其妙的迷茫... 学习内容: 1.使用多线程实现文件下载...   多线程下载是加快下载速度的一种方式..通过开启多个线程去执行一个任务..可以使任务的执行速度变快..多线程的任务下载时常都 ...

  5. 如何根据iframe内嵌页面调整iframe高宽续篇

    接着昨天的工作 如何根据iframe内嵌页面调整iframe高宽 来说,按照文章中说的第二种方法实现代码如下: 实现 A.com/detail/view 页面的iframe代码如下: <ifra ...

  6. IIS Express魔法堂:解除localhost域名的锁定

    一.前言   单点登录是通过域名从cookie中获取登录信息,然后再根据cookie的键值对获取用户信息.但由于通过IIS Express调试应用时默认使用localhost作为域名且无法直接修改,导 ...

  7. IOS开发UI基础UIControl事件

    UIControl事件1.UIControlEventTouchDown单点触摸按下事件:用户点触屏幕,或者又有新手指落下的时候. 2.UIControlEventTouchDownRepeat多点触 ...

  8. Device eth0 does not seem to be present,delaying initialization解决方法

    Bringing up interface eth0:  Device eth0 does not seem to be present, delaying initialization. 在linu ...

  9. PHP 表单验证--安全性--小记

    HTML 表单数据进行适当的验证对于防范黑客和垃圾邮件很重要! -------------------------------------------------------------------- ...

  10. Azure开发者任务之七:在Azure托管服务中托管WCF服务角色

    在一个托管服务中托管一个WCF服务角色和托管一个ASP.Net Web Role基本类似. 在上一篇文章中,我们学习了如何使用WCF Service Web Role. 在本文中,我会对上一篇文章进行 ...