Slide navigation: Forward with space bar, → arrow key, or PgDn. Backwards with ← or PgUp.

Copyright © Cay S. Horstmann 2016
@Test public void testEmptyInput() { ... }
instanceof checks, and method references.@Test(timeout=10000)
String, Class, or an enumerated type.@BugReport(showStopper=true,
assignedTo="Harry",
testCase=CacheTest.class,
status=BugReport.Status.CONFIRMED)timeout in @Test is 0L.value, you can omit the key:
@SuppressWarnings("unchecked") // Same as @SuppressWarnings(value="unchecked")@BugReport(reportedBy={"Harry", "Fred"})
@BugReport(reportedBy="Harry") // Same as {"Harry"}@BugReport(ref=@Reference(id=11235811), ...)
@Test @BugReport(showStopper=true, reportedBy="Joe") public void checkRandomInsertions()
@BugReport(showStopper=true, reportedBy="Joe")
@BugReport(reportedBy={"Harry", "Carl"})
public void checkRandomInsertions()enum) and interfaces (including annotation interfaces).
@Entity public class User { ... }@SuppressWarnings("unchecked") List<User> users = ...;
public User getUser(@Param("id") String userId)public class Cache<@Immutable V> { ... }@GPL(version="3") package com.horstmann.corejava; // Inpackage-info.javaimport org.gnu.GPL; // Imports theGPLannotation
public User getUser(@NonNull String userId)
// userId is assumed to be non-nullList<String> userIds and want to record the assumption that all elements are non-null.userIds variable.List<@NonNull String> userIds
@NonNull String[][] words, String @NonNull [][] words, String[] @NonNull [] words
if (text instanceof @Localized String) public String read() throws @Localized IOException List<@Localized ? extends Message> @Localized Message::getText
public boolean equals(@ReadOnly Object other)
this isn't mutated?public boolean equals(@ReadOnly Point this, @ReadOnly Object other)
public boolean equals(Point this, Object other)
.this parameter of an inner class constructor:
public class Sequence {
class Iterator implements java.util.Iterator<Integer> {
public Iterator(@ReadOnly Sequence Sequence.this) { ... }
}
...
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
long timeout();
...
}@interface declaration creates an actual Java interface.@Target and @Retention are meta-annotations: annotations of annotations.@Target specifies what this annotation can be applied to.@Retention specifies where the annotation can be accessed.
SOURCE, CLASS, RUNTIMEdefault clause after the interface method:
public @interface Test {
long timeout() default 0L;
...
}
public @interface BugReport {
String[] reportedBy() default {};
// Defaults to empty array
Reference ref() default @Reference(id=0);
// Default for an annotation
...
}@Deprecated annotation to mark deprecated features. If anyone uses them, the compiler will emit a warning.@Override annotation makes the compiler check that you really override a method:
public class Point {
@Override public boolean equals(Point other) { ... }
...
}
@SuppressWarnings annotation suppresses compiler warnings. Typical use:
@SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(cl, n);@FunctionalInterface annotation checks that an interface has a single abstract method:
@FunctionalInterface public interface IntFunction<R> {
R apply(int value);
}@Target and @Retention annotations:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test { ... }@Documented annotation indicates that the annotation should be included in documentation such as Javadoc.
@FunctionalInterface is documented, @SuppressWarnings is not.@Inherited applies to annotations for classes, and indicates that subclasses inherit the annotation:
@Inherited @interface Persistent { }
@Persistent class Employee { . . . }
class Manager extends Employee { . . . } // Also @Persistent@Repeatable indicates that an annotation can be applied multiple times.@Repeatable, you can apply the same annotation multiple times :
@TestCase(params="4", expected="24")
@TestCase(params="0", expected="1")
public static long factorial(int n) { ... }value is an array of annotations:
@TestCases({
@TestCase(params="4", expected="24"),
@TestCase(params="0", expected="1") })
public static long factorial(int n) { ... }@Repeatable(TestCases.class) @interface TestCase {
String params();
String expected();
}
@interface TestCases {
TestCase[] value();
}

@Deprecated has since and forRemoval attributes.java.util classes Observable, Observer (but not Vector, Hashtable).Object.finalize and Runtime.runFinalizersOnExit methods.toString format.toString methods, so we'll provide a static method ToStrings.toString(Object obj)obj and prints a string such as:
Point[x=5,y=10]
@ToString annotation to customize the format:
@ToString(includeName=false)
public class Point {
@ToString(includeName=false) private int x;
@ToString(includeName=false) private int y;
...
} Point objects are printed as [5, 10].@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ToString {
boolean includeName() default true;
}ToStrings.toString, get the annotation of the class and its fields:
Class<?> cl = obj.getClass();
ToString classAnnotation = cl.getAnnotation(ToString.class);
for (Field f : cl.getDeclaredFields()) {
ToString fieldAnnotation = f.getAnnotation(ToString.class);
if (fieldAnnotation.includeName()) ...
...
}
getAnnotationsByType(cl) to get an array of the annotations.ToStrings example, we can generate source code for that utility class:
public class ToStrings {
public static String toString(Point obj) {
Generated code
}
public static String toString(Rectangle obj) {
Generated code
}
...
public static String toString(Object obj) {
return Objects.toString(obj);
}
}ToStrings Class@ToString public class Rectangle {
...
@ToString(includeName=false) public Point getTopLeft() { return topLeft; }
@ToString public int getWidth() { return width; }
@ToString public int getHeight() { return height; }
}public static String toString(Rectangle obj) {
StringBuilder result = new StringBuilder();
result.append(“Rectangle[”);
result.append(toString(obj.getTopLeft()));
result.append(“,width=”);
result.append(toString(obj.getWidth()));
result.append(“,height=”);
result.append(toString(obj.getHeight()));
result.append(“]”);
return result.toString();
}javac -processor ToStringAnnotationProcessor *.java
-XprintRounds flag.javax.lang.model API:
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment currentRound) {
...
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(
"com.horstmann.annotations.ToStrings");
PrintWriter out = new PrintWriter(sourceFile.openWriter());
Print code for package and class
for (Element e : currentRound.getElementsAnnotatedWith(ToString.class)) {
if (e instanceof TypeElement) {
TypeElement te = (TypeElement) e;
Print code for toString method
}
}
}javac com/horstmann/annotations/ToStringAnnotationProcessor.java javac -processor com.horstmann.annotations.ToStringAnnotationProcessor sourcelevel/*.java java sourcelevel.SourceLevelAnnotationDemo
public static void premain(String arg, Instrumentation instr)
Premain-Class: MyAgent
jar cvfm MyAgent.jar manifest.mf *.class
java -javaagent:MyAgent.jar=agentArgument MyProg
@LogEntry(logger=loggerName)Logger.getLogger(loggerName).entering(className, methodName);
May 17, 2016 10:57:59 AM Item hashCode FINER: ENTRY
LogEntry annotation.ldc loggerName invokestatic java/util/logging/Logger.getLogger:(Ljava/lang/String;)Ljava/util/logging/Logger; ldc className ldc methodName invokevirtual java/util/logging/Logger.entering:(Ljava/lang/String;Ljava/lang/String;)V
javac -classpath .:../asm-5.1/lib/\* bytecodeAnnotations/EntryLoggingAgent.java jar cvfm bytecodeAnnotations/EntryLoggingAgent.jar bytecodeAnnotations/EntryLoggingAgent.mf \ bytecodeAnnotations/Entry*.class javac set/SetTest.java java -javaagent:bytecodeAnnotations/EntryLoggingAgent.jar=set.Item -classpath .:../asm-5.1/lib/\* set.SetTest