如何解决在编译时检查传递给方法的字符串参数是否具有@deprecated注释
|| 我想验证是否不赞成使用传递给方法的字符串。例如。:public class MyRepo
@Deprecated
private static final String OLD_PATH = \"old_path\";
private static final String NEW_PATH = \"new_path\";
//...
public load(Node node){
migrateProperty(node,OLD_PATH,NEW_PATH );
//load the properties
loadProperty(node,NEW_PATH);
}
//I want to validate that the String oldPath has the @Deprecated annotation
public void migrateProperty(Node node,String oldPath,String newPath) {
if(node.hasProperty(oldPath)){
Property property = node.getProperty(oldPath);
node.setProperty(newPath,(Value) property);
property.remove();
}
}
//I want to validate that the String path does not have the @Deprecated annotation
public void loadProperty(Node node,String path) {
//load the property from the node
}
}
我能找到的最接近的是验证参数本身的注释。
解决方法
您的注释将字段“ 1”标记为已弃用,而不是字符串“ 2”。在对“ 3”的调用中,您传递字符串,而不是字段。因此,该方法不知道该值来自的字段,因此无法检查它的注释。
通过注释,您可以声明有关Java元素的信息,例如类,字段,变量,方法。您不能注释对象,例如字符串。
您链接到的文章讨论了注释形式参数。同样,被注释的是参数,而不是参数(传递的值)。如果将@Something放入方法参数,则此参数将始终与该方法的调用者传递的值无关地进行注释。
您可以执行以下操作-但是我不确定这是否是您想要的-
@Deprecated
private static final String OLD_PATH = \"old_path\";
private static final String NEW_PATH = \"new_path\";
public load(Node node){
migrateProperty(node,getClass().getDeclaredField(\"OLD_PATH\"),getClass().getDeclaredField(\"NEW_PATH\") );
// ...
}
//I want to validate that the String oldPath has the @Deprecated annotation
public void migrateProperty(Node node,Field<String> oldPath,Field<String> newPath) {
if ( oldPath.getAnnotation(Deprecated.class) == null ) {
// ... invalid
}
// ...
}
在这种情况下,您实际上传递的是字段,而不是值。
, 已弃用\“ old \”(基于JavaDoc的Java 5之前的版本)的注释存储在已编译的类文件中,但不幸的是无法通过反射访问。
如果您可以选择使用\“ real \”注释(@ java.lang.Deprecated),则当然可以使用反射来获取类的所有声明字段,并检查它们是否为带@的静态字符串。不推荐使用的注释,并将其与传递的方法参数进行比较。
但是,这听起来很丑陋,我鼓励您找到另一种方法来检查不需要的参数。
, 首先,您的\“ @ deprecated \”标记只是JavaDoc标记,而不是注释,因此它与编译器无关。
如果使用ѭ5批注,则会在不赞成使用的行的行中收到不赞成使用的警告:
@Deprecated
private static final String OLD_PATH = \"old_path\";
private static final String NEW_PATH = \"new_path\";
您也可以保留JavaDoc@deprecated
标记,但是只有提供一些解释后,它才有用。当然,javadoc标记必须在ѭ8内。
但是,如果您想在运行时在migrateProperty()
方法内检查所传递的字符串来自不赞成使用的变量,那是不可能的。通过方法调用得到的是对堆上String的引用。弃用仅是指该字段,也许只能在调用该方法之前进行检查。
, 我不知道您的用例到底是什么,但是我不认为您可以使用@Deprecated来完成您想做的事情。当您将某项标记为不赞成使用时,您是在将字段,方法或类标记为NOT值。您可以在loadProperty中访问的就是值。
因此,以您的例子为例,我可以很容易地打电话给
new MyRepo().loadProperty(\"old_path\");
完全不参考OLD_PATH或NEW_PATH。解决方案很简单,您需要显式检查方法是否匹配。 (已添加isDeprecated方法)。您可以根据需要保留@Deprecated批注。
public class MyRepo {
@Deprecated
private static final String OLD_PATH = \"old_path\";
private static final String NEW_PATH = \"new_path\";
private boolean isDeprecated(String path) {
return OLD_PATH.equals(\"old_path\");
}
//...
public load(Node node){
migrateProperty(node,OLD_PATH,NEW_PATH );
//load the properties
loadProperty(node,NEW_PATH);
}
//I want to validate that the String oldPath has the @Deprecated annotation
public void migrateProperty(Node node,String oldPath,String newPath) {
if (!isDeprecated(oldPath)) {
throw new Exception(oldPath + \" is not deprecated\");
}
if(node.hasProperty(oldPath)){
Property property = node.getProperty(oldPath);
node.setProperty(newPath,(Value) property);
property.remove();
}
}
//I want to validate that the String path does not have the @Deprecated annotation
public void loadProperty(Node node,String path) {
if (isDeprecated(path)) {
throw new Exception(path + \" is deprecated,please use \" + NEW_PATH);
}
//load the property from the node
}
}
如果需要将此模式应用于多个类,那么您当然可以使其更加严格。
, \ .class \文件的检查是否符合您的“ compile”时间要求? FindBug允许对.class文件进行许多检查。您可以编写自定义插件来检查字段,方法和参数(以及许多其他内容)。这是一个旧教程
如果您设法编写一个代码,那么我将对使用该代码非常感兴趣:)
, 我的方法是将其更改为编译器已经擅长的类型:类型检查。
基于示例中常量的使用,我将假设您具有一组已知的潜在值,这表明enum
s。
public class MyRepo
private enum Preferred {
PATH(\"new_path\"),OTHER_THING(\"bar\");
private String value;
Preferred(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}
private enum Legacy {
PATH(\"old_path\"),OTHER_THING(\"foo\");
private String value;
Legacy(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}
public load(Node node){
migrateProperty(node,Legacy.PATH,Preferred.PATH);
//load the properties
loadProperty(node,Preferred.PATH);
}
public void migrateProperty(Node node,Legacy oldBusted,Preferred newHotness) {
if (node.hasProperty(oldBusted)) {
Property property = node.getProperty(oldBusted);
node.setProperty(newHotness,(Value) property);
property.remove();
}
}
public void loadProperty(Node node,Preferred path) {
//load the property from the node
}
}
如果这不符合您的需求,请添加有关使用情况以及您要解决的根本问题的更多信息。
如果您真的想通过注释来完成此任务,那么看来有一种方法。 Java 6在ѭ14中内置了批注处理API,它们似乎实际上是编译器的插件。他们可以做您想要做的事情,还有很多其他事情,但至少在乍一看时,它们似乎很深奥。这看起来像一个不错的介绍:http://today.java.net/pub/a/today/2008/04/10/source-code-analysis-using-java-6-compiler-apis.html
,根本不可能在编译时执行此操作。
首先,@Depreciated批注可以引用String字段,但是无论如何都没有附加字符串值。
其次,即使您可以以某种方式标记带有注释的字符串值,Java类型系统中的任何内容都不能让您声明只能传递带有特定注释的值-注释信息甚至在编译时也不一定可用。
由于第1点,注释处理不起作用。由于第2点,所有其他方案仅在运行时起作用。
要实现编译时检查,最自然的做法是创建一个包含字符串的所有有效值的枚举。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。