Effective Java 35 Prefer annotations to naming patterns
Disadvantages of naming patterns
- Typographical errors may result in silent failures.
- There is no way to ensure that they are used only on appropriate program elements.
- 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();
}
- 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.
- 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.
- 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的更多相关文章
- 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 ...
- Effective Java 53 Prefer interfaces to reflection
Disadvantage of reflection You lose all the benefits of compile-time type checking, including except ...
- 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 ...
- Effective Java 18 Prefer interfaces to abstract classes
Feature Interface Abstract class Defining a type that permits multiple implementations Y Y Permitted ...
- Effective Java 20 Prefer class hierarchies to tagged classes
Disadvantage of tagged classes 1. Verbose (each instance has unnecessary irrelevant fields). 2. Erro ...
- Effective Java 25 Prefer lists to arrays
Difference Arrays Lists 1 Covariant Invariant 2 Reified at runtime Erased at run time 3 Runtime type ...
- 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 ...
- 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 ...
- 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 ...
随机推荐
- Redis设计与实现-持久化篇
redis数据库 默认16个数据库,每个数据库由一个redis.h/redisDb结构表示,此结构里的dict字典与expires字典,其中dict保存了该库所有键值对,此字典即为键空间:expire ...
- [ASP.NET]谈谈REST与ASP.NET Web API
13天的假期结束,赶紧回来充电了 本节目录 Web API简介 自我寄宿 IIS寄宿 调用Web API Web API原理 Web API简介 REST REST是“REpresentational ...
- 【Win10】单元测试中捕获异步方法的指定异常
温馨提醒:本文需要知道什么是单元测试才能阅读. 在之前 WPF.ASP.NET 中,单元测试要捕捉指定异常,我们是通过 ExpectedExceptionAttribute 来实现的.如下图: 但是, ...
- .Net反射机制分析和使用
1..NET反射的概述 .NET反射是审查元数据并动态收集关于它的类型信息的能力. 应用程序结构分为应用程序域—程序集—模块—类型—成员几个层次,公共语言运行库加载器管理应用程序域.这些域在拥有相同应 ...
- 很有趣的Java分形绘制
部分与整体以某种形式相似的形,称为分形. 首先我们举个例子: 我们可以看到西兰花一小簇是整个花簇的一个分支,而在不同尺度下它们具有自相似的外形.换句话说,较小的分支通过放大适当的比例后可 ...
- WebApi传参总动员(四)
前文介绍了Form Data 形式传参,本文介绍json传参. WebApi及Model: public class ValuesController : ApiController { [HttpP ...
- [转载]Ubuntu14.04 LTS更新源
不同的网络状况连接以下源的速度不同, 建议在添加前手动验证以下源的连接速度(ping下就行),选择最快的源可以节省大批下载时间. 首先备份源列表: sudo cp /etc/apt/sources.l ...
- 发布在IIS的网站,可以用本机IP登录访问,用localhost不可登录访问
之前在IIS发布一个测试的网址,但是用本机IP可以访问,用localhost不可访问
- Mybatis Physical Pagination
1. Requirements: when we use the sql like "select * from targetTable", we get all records ...
- R语言-神经网络包RSNNS
code{white-space: pre;} pre:not([class]) { background-color: white; }if (window.hljs && docu ...