我想验证传递给方法的字符串是否已弃用。 e.g:
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
}
}
我能找到的最近的是validating annotations on the parameters themselves。
答案 0 :(得分:1)
您的注释将字段OLD_PATH
标记为已弃用,而不是字符串"old_path"
。在调用migrateProperty
时,您传递字符串,而不是字段。因此,该方法不知道值来自的字段,也无法检查它是否有注释。
使用注释,您可以陈述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
}
// ...
}
在这种情况下,你真的通过了这个领域,而不是它的价值。
答案 1 :(得分:0)
首先,您的“@deprecated”标记只是一个JavaDoc标记,而不是注释,因此它与编译器无关。
如果您使用@Deprecated
注释,您将获得使用已弃用字段的行的弃用警告:
@Deprecated
private static final String OLD_PATH = "old_path";
private static final String NEW_PATH = "new_path";
您也可以保留JavaDoc @deprecated
标记,但只有在您提供一些解释时它才有用。当然,javadoc标签必须位于/** ... */
内。
但是,如果要在运行时检查字符串传递的migrateProperty()
方法中的运行时来自已弃用的变量,则这是不可能的。您通过方法调用获得的是对堆上的String的引用。弃用仅引用该字段,可能只能在调用方法之前检查该字段。
答案 2 :(得分:0)
“旧”(Java 5之前,基于JavaDoc)不推荐使用的注释存储在已编译的类文件中,但遗憾的是无法通过反射访问。
如果您可以选择使用“真实”注释(@ java.lang.Deprecated),您当然可以使用反射来获取类的所有声明字段,检查它们是否是静态字符串@Deprecated注释并将它们与传递的方法参数进行比较。
然而,这听起来相当丑陋,我鼓励你找到一种不同的方法来检查不需要的参数。
答案 3 :(得分:0)
我不知道你的用例到底是什么,但我认为你不能用@Deprecated做你想做的事。当您将某些内容标记为已弃用时,您将标记字段,方法或类而不是值。您在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
}
}
如果需要将此模式应用于多个类,您当然可以使其更加严谨。
答案 4 :(得分:0)
检查“.class”文件是否适合您的“编译”时间要求? FindBug允许对.class文件进行多次检查。您可以编写自定义插件来检查字段,方法和参数(以及许多其他内容)。这是一个旧tutorial
如果你设法写一个,我将非常有兴趣使用该代码:)
答案 5 :(得分:0)
我的方法是将其改为编译器已经擅长的东西:类型检查。
根据您示例中常量的使用,我将假设您有一组已知的潜在值,这表示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具有内置于javac
的注释处理API,它们似乎是编译器的有效插件。他们可以做你想要的事情加上更多,但它们看起来相当深奥,至少在第一眼看上去。这看起来很好:http://today.java.net/pub/a/today/2008/04/10/source-code-analysis-using-java-6-compiler-apis.html
答案 6 :(得分:0)
在编译时根本无法做到这一点。
首先,@ Distreciated注释可以引用一个String字段,但不会以任何方式附加字符串值。
其次,即使您以某种方式使用注释标记字符串值,Java类型系统中的任何内容都不允许您声明只能传递具有特定注释的值 - 注释信息在编译时甚至不可用时间。
由于第1点,注释处理将不起作用。由于第2点,所有其他方案仅在运行时工作。
要实现编译时检查,最自然的方法是创建一个包含字符串的所有有效值的枚举。