Java 仅限公共访问的注释
我想强制执行此注释只能放置在公共成员(字段或方法)上。这可能吗?我对这个话题的简短研究表明没有Java 仅限公共访问的注释,java,reflection,annotations,Java,Reflection,Annotations,我想强制执行此注释只能放置在公共成员(字段或方法)上。这可能吗?我对这个话题的简短研究表明没有 @Target({ElementType.FIELD,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface CsvAttribute { String columnName(); int position(); } 我的目标是不使用try-catch块来实现这一点。既然我可以访问对象,
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CsvAttribute {
String columnName();
int position();
}
我的目标是不使用try-catch块来实现这一点。既然我可以访问对象,我可以不经反射地执行此操作吗
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 "";
}
}
公共抽象类CsvExportable{
受保护的最终地图转换程序{
final方法[]m=this.getClass().getDeclaredMethods();
返回新的ArrayList(Arrays.asList(m)).stream()
.filter(p->p.isAnnotationPresent(csvatAttribute.class))
.collect(collector.toMap)(
p->p.getAnnotation(csvatAttribute.class).position(),
p->this.invokeGetter(p));
}
私有字符串调用器(方法m){
试一试{
返回Objects.toString(m.invoke(this),“”);
}捕获(IllegalAccessException | InvocationTargetException e){
LOG.error(“@csvatAttribute注释必须放在公共getter上!”);
e、 printStackTrace();
}
返回“”;
}
}
不据我所知,如果不考虑到需要进行注释处理,您无法在不进行反射的情况下执行此操作。您可以使用修饰符#isPublic来确定字段或方法是否是公共的。如果要支持所指示的方法,还应使用ElementType.METHOD
另一方面,请随意查看或查看一些反射API,它们可能会让您的生活更轻松
//如果是方法或字段
如果(!Modifier.isPublic(方法)){
抛出新的IllegalStateException(“修饰符必须是公共的”);
}
//如果一个字段
如果(!Modifier.isPublic(字段)){
抛出新的IllegalStateException(“修饰符必须是公共的”);
}
@Target({ElementType.FIELD,ElementType.METHOD})
不据我所知,如果不考虑到需要进行注释处理,您无法在不进行反射的情况下执行此操作。您可以使用修饰符#isPublic来确定字段或方法是否是公共的。如果要支持所指示的方法,还应使用ElementType.METHOD
另一方面,请随意查看或查看一些反射API,它们可能会让您的生活更轻松
//如果是方法或字段
如果(!Modifier.isPublic(方法)){
抛出新的IllegalStateException(“修饰符必须是公共的”);
}
//如果一个字段
如果(!Modifier.isPublic(字段)){
抛出新的IllegalStateException(“修饰符必须是公共的”);
}
@Target({ElementType.FIELD,ElementType.METHOD})
不可能在注释本身中进行配置,但如果有编译时注释处理器,可以在编译时注释处理器中进行配置。如果带注释的元素无效,只需抛出异常即可
如果您只是在运行时处理注释,那将没有多大帮助。您可以触发运行时异常,但不会出现编译错误。无法在注释本身中配置该异常,但如果有编译时注释处理器,您可以在编译时注释处理器中进行配置。如果带注释的元素无效,只需抛出异常即可
如果您只是在运行时处理注释,那将没有多大帮助。您可以触发运行时异常,但不会出现编译错误。即使强制注释仅出现在
public
成员中,编译器也不知道方法始终表示public
方法。因此,它将继续坚持捕获IllegalAccessException
。此外,无论该方法是否为public
,它都可能抛出异常,因此,您始终必须处理InvocationTargetException
。换句话说,无论如何都无法绕过try-catch块。顺便问一下,StringUtils.EMPTY
的意义是什么,尤其是当您也在同一方法中使用直截了当的“
”时?命名常量在名称告诉您一些事情时很有用,但在名称告诉您的内容不超过常量本身时就不有用了。每个人都可以看到,“
是一个空字符串,因此仅用单词empty
说同样的话并不能证明向第三方库添加依赖项是合理的。另一个故事是“@csvatribute注释必须放在public getter上!”
常量,它甚至包含一个隐式假设,即该方法是用@csvatribute
注释的,它不在invokeGetter
方法的范围内,但这仍然是调用方的责任,因此日志消息将是在类范围内声明的常量的自然候选。无论如何,考虑到你的实际问题,我想知道你是否认为相反;当您使用java.lang.invoke
API时,您可以放弃方法必须是public
的要求。顺便说一句,新建ArrayList(Arrays.asList(m)).stream()
做了两次不必要的迂回:不需要复制通过Arrays.asList(m)创建的List
进入数组列表
,就像数组一样。asList(m).stream()
也可以,但是你甚至可以在没有任何列表的情况下创建流
:只要数组。stream(m)
。这就是我在第一条评论中说的,即使你强制该方法公开,try-catch块将保留。但我不是说使用setAccessible(true)
,而是说使用java.lang.invoke
API,它允许调用方将必要的访问权限转移到实用工具方法,这样它就不会因为访问权限不足而失败。还可以选择为访问器方法生成Function
对象,每个类只需执行一次,因此后续使用不再需要try-catch块。不过,初始化将更加复杂