Reputation: 95
I want to enforce that this annotation can only be placed on public members, either field or method. Is this possible? My brief research on this topic said no.
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CsvAttribute {
String columnName();
int position();
}
My goal is to achieve this without the try-catch block. Since I have access to the object can I do this without reflection?
public abstract class CsvExportable {
protected final Map<Integer, String> convertFieldsToMap(){
final Method[] m = this.getClass().getDeclaredMethods();
return new ArrayList<>(Arrays.asList(m)).stream()
.filter(p -> p.isAnnotationPresent(CsvAttribute.class))
.collect(Collectors.toMap(
p -> p.getAnnotation(CsvAttribute.class).position(),
p -> this.invokeGetter(p)));
}
private String invokeGetter(Method m){
try {
return Objects.toString(m.invoke(this), "");
} catch (IllegalAccessException | InvocationTargetException e) {
LOG.error("@CsvAttribute annotation must be placed on public getters!");
e.printStackTrace();
}
return "";
}
}
Upvotes: 0
Views: 349
Reputation:
It's not possible to configure that in the annotation itself, but you can do it in your compile time annotation processor if you have one. Simply throw an exception if the annotated element is not valid.
If you're only processing the annotation at runtime, that won't help much. You can trigger a runtime exception, but no compilation error.
Upvotes: 1
Reputation: 5246
No to my knowledge you cannot do this without reflection considering you need to do annotation processing. You can use Modifier#isPublic to determine if the Field or Method is public. You should also use ElementType.METHOD if you want to support methods as well as indicated.
On an unrelated note, feel free to check out ClassGraph or Reflections for some reflection apis that might make your life easier.
// if a method or field
if (!Modifier.isPublic(method)) {
throw new IllegalStateException("Modifier must be public.");
}
// if a field
if (!Modifier.isPublic(field)) {
throw new IllegalStateException("Modifier must be public.");
}
@Target({ ElementType.FIELD, ElementType.METHOD })
Upvotes: 1