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. 自增长的聚集键值不会扩展(scale)

    如何选择聚集键值的最佳实践是什么?一个好的聚集键值应该有下列属性: 范围小的(Narrow) 静态的(Static) 自增长的(Ever Increasing) 我们来具体看下所有这3个属性,还有在S ...

  2. Django--models表操作

    需求 models对表的增删改查 知识点 1.基础操作 1.1  增 方法一 1 models.Tb1.objects.create(c1='xx', c2='oo')  #增加一条数据 1 2 di ...

  3. Websocket协议的学习、调研和实现

    本文章同时发在 cpper.info. 1. websocket是什么 Websocket是html5提出的一个协议规范,参考rfc6455. websocket约定了一个通信的规范,通过一个握手的机 ...

  4. 价值100W的经验分享: 基于JSPatch的iOS应用线上Bug的即时修复方案,附源码.

    限于iOS AppStore的审核机制,一些新的功能的添加或者bug的修复,想做些节日专属的活动等,几乎都是不太可能的.从已有的经验来看,也是有了一些比较常用的解决方案.本文先是会简单说明对比大部分方 ...

  5. 2015 Multi-University Training Contest 1 - 1009 Annoying problem

    Annoying problem Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5296 Mean: 给你一个有根树和一个节点集合 ...

  6. 2016C#模拟谷歌Google登陆Gmail&Youtube小案例

    之所以写这个,是因为本来想写一个Youtube刷评论的工具,把登录做出来了,后面就没继续做下去. 涉及到基本的HttpWatch的应用以及Fiddler的应用(Fd主要用来排查问题,通过对比 浏览器和 ...

  7. 安装win8、ubuntu双系统的过程

    弄了一个晚上,终于完成了,之前是用虚拟机的,但是觉得不带劲,并且折腾来时菜鸟变大神的捷径,虽然现在还一直在爬坑.继续奋斗吧...王小二 首先是看 ubuntu 百度贴吧的安装帖子(http://tie ...

  8. jQuery中常用的元素查找方法

    $("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myElement所以得到的是唯一的元素 $("div&q ...

  9. Studio for Winforms FlexGrid: 创建分类汇总

    C1FlexGrid.Subtotal方法可以增加包含普通(非小计)行的汇总数据的分类汇总行. 分类汇总支持分层聚合.例如,如果你的表格包含销售数据,你可能会通过产品.地区和推销员来小计一下以得出总的 ...

  10. 找到MVC框架中前端URL与后端同步的解决方案

    基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...