Indeed, you can't instantiate the config class. But what you can do, is query which annotations are on the config class.
So, you could imagine the following system:
old way:
@Movie(
name = "A Few Good Men",
director = @Director(lastName = "Reiner", firstName = "Rob"),
releaseYear = 1992,
liked = true)
public class Foo {}
@Movie(
name = "A Few Good Men",
director = @Director(lastName = "Reiner", firstName = "Rob"),
releaseYear = 1992,
liked = true)
public class Bar {}
new way:
@Movie(
name = "A Few Good Men",
director = @Director(lastName = "Reiner", firstName = "Rob"),
releaseYear = 1992)
public class Placeholder {
// This class serves solely as a place to store the above annotation.
private Placeholder() {}
}
@Movie(
config = Placeholder.class,
liked = true)
public class Foo {}
@Movie(
config = Placeholder.class,
liked = false)
public class Bar {}
Your rule would presumably be that anything explicitly set on the actual class is taken, and if there is nothing explicitly set but there is a 'config' class set, then the value from the annotation on that config class is taken.
Unfortunately, there's no (non-hacky) way to tell the difference between @Foo and @Foo(value="") when Foo is defined as @interface Foo {String value() default "";} - i.e. there is no way to differentiate an explicit setting of a value that is the same as the default value for a given anno parameter, so you can't actually use 'if you do not explicitly set it, then this defaulting mechanism applies' as a concept in annotations. Therefore, 'use the defaulting mechanism' must be based on the actual value - you need 'stand-in' values that mean: "Inherit from config". That means booleans are right out, unfortunately. You can use enums instead.
Here is an example:
public enum LikeStatus {
LIKED, DISLIKED, INHERIT;
}
// target classes/types
public @interface Movie {
Class<?> config() default Object.class;
LikeStatus liked default LikeStatus.INHERIT;
int releaseYear() default 0;
Director director() default @Director(lastName = "", firstName = "")
String name() default "";
}
and now you need to write some code that knows about the defaults and acts accordingly (so, if name() returns an empty string, that means you should check the config class for the Movie annotation and fetch its name. Same for a release year of 0, a director with a blank first and last name, and so on.