我仍然是Java编程的新手,我正在查看一个开源项目并遇到了这个
public @TileNetworkData int progressPart = 0;
之前我曾见过@
的使用,但只是在成员之前做@override
之类的事情。令我惊讶的是查找了它带给我用户代码的定义
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TileNetworkData {
int staticSize () default -1;
}
这段代码在做什么,它对什么有用?看起来它正在向该字段添加某种形式的元数据。如何使用这样的东西?
做一些谷歌我发现这被称为“注释”但是附在它上面的一切都超出了我的想象。将会使用任何类似这样的例子。
答案 0 :(得分:5)
Annotations用作“机器可读元数据” - 它们以编译器和运行时可以解析甚至可能理解的方式描述它们标记的字段,方法和类。如果您熟悉.NET's attributes,则会发现Java注释的使用方式类似。
例如,示例中定义的TileNetworkData
注释本身使用注释Retention(RetentionPolicy.RUNTIME)
进行修饰。这告诉编译器将TileNetworkData注释嵌入到它注释的字段的字节码中。相同的注释也告诉Java运行时,当它使用TileNetworkData注释字段加载类时,它应该保留TileNetworkData注释以进行运行时反射。
现在,您的代码可以反映对象的字段以查找TileNetworkData注释,并对带有注释的字段执行某些操作:
// I haven't even compiled this code, and even if it works, it's still insane.
// (others who know annotations better should feel free to edit or replace)
public void copyTileNetworkDataToCache (Object data, Cache<?> cache) {
for (Field f : data.getClass().getFields()) {
if (f.isAnnotationPresent(TileNetworkData.class)) {
cache.save(f.get(data));
}
}
}
您甚至可以使用JDK 5中的apt
前端和JDK 6及更高版本中的javac
开关编写教授Java编译器how to interpret your annotations at compile time的代码。要构成另一个蹩脚的示例,访问磁贴网络可能需要很长时间,以至于您希望尽可能避免使用来自它的数据。因此,您可能希望列出包含TileNetworkData-annotated字段的所有类,因此您可以查看所有类,并可能重写那些不一定需要访问tile网络的类。为此,您可以编写一个打印出所有匹配类的注释处理器,然后在编译时将apt
指向处理器。
答案 1 :(得分:4)
示例:事务划分:
public class TransactionalThing {
@Transactional
public void doSomePersistenceStuff() {
Foo foo = loadAFoo();
doSomeStuffWith(foo);
foo.setProcessed(true);
}
}
还有其他代码可以查找由@Transactional
注释的方法,在调用方法之前启动事务,并在事务完成时提交(或回滚)事务。您还可以在注释中添加有关诸如回滚规则之类的信息:
@Transactional(rollbackFor = SomeException.class,
noRollbackFor = SomeOtherException.class)
再一次,只需要扫描这些事务的代码来读取这些属性并正确处理事情。
答案 2 :(得分:2)
注释用于元数据,用于描述方法,类和其他类型的对象。
您可以使用它来为您的java类分配元数据(数据描述)。经典的例子是 @Deprecated ,它将方法标记为“将来不再使用”。
例如,您可以使用它们将配置信息添加到java类。如果您正在使用Hibernate(ORM),则向类添加注释,说明应该从数据库表table_xxx
中包含的信息填充此类,并且应将列column_xxx
信息存储在在课堂上这样的领域。
您发布的代码是定义注释。这将允许此注释在代码中的其他位置使用。它表示注释将在运行时@Retention(RetentionPolicy.RUNTIME)
可用,并且Annotation应该对使用它的类和该类的任何子类都可用。
答案 3 :(得分:1)
可以通过反射查询元数据。因此,如果代码中某处存在泛型void submitTileNetworkData(Object model)
,它可以迭代model
的字段并构建基于TileNetworkData注释的二进制转储。