In General
You can't annotate an object (that exists at runtime only). You just can annotate a declaration or, since Java 8, a type usage (that exists already at compile time).
See The Java™ Tutorials, Annotations, Annotations Basics:
Where Annotations Can Be Used
Annotations can be applied to declarations: declarations of classes, fields, methods, and other program elements. [...]
As of the Java SE 8 release, annotations can also be applied to the use of types.
and The Java™ Tutorials, Annotations, Type Annotations [...]:
Before the Java SE 8 release, annotations could only be applied to declarations. As of the Java SE 8 release, annotations can also be applied to any type use. This means that annotations can be used anywhere you use a type. A few examples of where types are used are class instance creation expressions (new), casts, implements clauses, and throws clauses. This form of annotation is called a type annotation [...].
and the unfailingly ultimate source The Java® Language Specification, 9.6.4. Predefined Annotation Types:
9.6.4.1. @Target
Annotation types may be applicable in declaration contexts, where annotations apply to declarations, or in type contexts, where annotations apply to types used in declarations and expressions.
[Emphases by me.]
Anwer to your question
As @M.Prokhorov mentions in his comment to your question you're not annotating your House
class but the local variable declaration of house
, that is of type House
.
See also this Java Annotations Tutorial:
Annotation Placement
You can place Java [declaration] annotations above classes, interfaces, methods, method parameters, fields and local variables.
[...]
Creating Your Own Annotations
[...]
@Retention
[...]
@Retention(RetentionPolicy.RUNTIME)
This is what signals to the Java compiler and JVM that the annotation should be available via reflection at runtime.
[...]
RetentionPolicy.CLASS
means that the annotation is stored in the .class file, but not available at runtime. This is the default retention policy, if you do not specify any retention policy at all.
[Emphases by me.]
That means you have to declare your Spooky
annotation with:
@Retention( RetentionPolicy.RUNTIME )
public @interface Spooky {}
However, as @LouisWasserman mentions in his comment to your question:
I don't believe there's any way to get the annotations from a local variable.
See also the SO question ElementType.LOCAL_VARIABLE annotation type and the aforementioned JLS:
9.6.4.1. @Target
[...]
An annotation on a local variable declaration is never retained in the binary representation.
So, if you'd make house
a field (a.k.a. member variable):
@Spooky
private House house = new House();
you could use:
Stream.of( this.getClass().getDeclaredFields() )
.forEach( field -> Stream.of( field.getAnnotations() )
.forEach( annotation -> System.out.printf( "@%s%n%s %s %s;%n",
annotation.annotationType().getSimpleName(),
Modifier.toString( field.getModifiers() ),
field.getType().getSimpleName(),
field.getName() ) ) );
or if you want to get the house
field specifically:
try {
final Field field = this.getClass().getDeclaredField( "house" );
final Spooky spooky = field.getAnnotation( Spooky.class );
if ( spooky != null ) {
System.out.printf( "@%s%n%s %s %s;%n",
spooky.annotationType().getSimpleName(),
Modifier.toString( field.getModifiers() ),
field.getType().getSimpleName(),
field.getName() );
}
}
catch ( NoSuchFieldException | SecurityException e ) {
e.printStackTrace();
}
Output in both cases:
@Spooky
private House house;
But, as you see, even with the conciseness of streams your code doesn't become clearer with that. I'd consider the suggestions made in the comments to your questions.