对注释进行类型转换-如何/为什么这样做?
你能帮我理解 (1) 的类型转换是如何/为什么工作的吗?我找不到任何表明 Java 注释类型可以类型转换为接口类型的内容。
org.junit.Test //this is an annotation
junit.framework.Test //this is an interface
只是我没有看到 org.junit.Test 和 junit.framework.Test 之间的关系
import org.junit.Test;
import junit.framework.AssertionFailedError;
import junit.framework.TestResult;
public class TestJunit3 extends TestResult {
// add the error
public synchronized void addError(Test test, Throwable t) {
super.addError((junit.framework.Test) test, t); //how does this typecast work (1)
}
// add the failure
public synchronized void addFailure(Test test, AssertionFailedError t) {
super.addFailure((junit.framework.Test) test, t);
}
@Test
public void testAdd() {
// add any test
}
// Marks that the test run should stop.
public synchronized void stop() {
//stop the test here
}
}
回答
根据Java 语言规范 (JLS) 第 9.6 章,注释是“一种特殊的接口类型”。事实上,它甚至说:
每个注解类型的直接超接口是
java.lang.annotation.Annotation.
如果我们查看文档,我们可以看到它java.lang.annotation.Annotation实际上是一个接口。我可以在这里想到两种可能的情况,这将涉及摆脱我的头顶。请注意,这不是一个详尽的列表。有许多不同的方法来设计类型层次结构。
场景一
接口可以扩展任何其他接口,因此您可以拥有一个扩展注释的接口。然后你需要转换到子接口,像这样:
public @interface MyAnnotation { }
<
public interface MyInterface extends MyAnnotation { }
pre>public @interface MyAnnotation { }
public @interface MyAnnotation { }
public interface MyInterface extends MyAnnotation { }
public class MyClass implements MyInterface {
// You have to implement the abstract method:
@Override
public Class<? extends Annotation> annotationType() {
return MyAnnotation.class;
}
}
public class Driver {
public static void main(String[] args) {
// Implicit cast to super:
MyAnnotation annot = new MyClass();
// Now we have to explicitly cast back down to an interface:
MyInterface inter = (MyInterface) annot;
}
}
场景二
将实例强制转换为其超类型之一应该是合法的。是的,这不是必需的,但它应该是合法的,因此您可以使用以下代码:
@MyAnnotation public class MyClass { }
public class Driver {
public static void main(String[] args) {
// Redundant, but legal cast:
Annotation annot = (Annotation) MyClass.class.getAnnotations()[0];
}
}
限制
请注意,JLS 说:
根据 AnnotationTypeDeclaration 语法,注释类型声明不能是通用的,并且不允许扩展子句。
这意味着您不能将注释作为除java.lang.annotation.Annotation.
JLS 还说:
注释类型不能显式声明超类或超接口这一事实的结果是,注释类型的子类或子接口本身永远不是注释类型。
这意味着以下代码将是非法的:
// Illegal because MyInterface is not an annotation type:
@MyInterface public class MyClass { }
你的场景
你有两个接口,org.junit.Test和junit.framework.Test. 是的,org.junit.Test是一个注解,但所有注解都是接口,正如我上面解释的那样。现在考虑一个实现两个接口的类:
public class MyClass implements org.junit.Test, junit.framework.Test {
// You would have to implement all the methods here
}
考虑以下驱动程序代码,并注意从org.junit.Testto的合法、合法的强制转换junit.framework.Test:
public class Driver {
public static void main(String[] args) {
// Implicit cast, because MyClass is a subtype of org.junit.Test:
org.junit.Test test1 = new MyClass();
// Here we need an explicit cast, but it's still legal.
// test1 is still an instance of MyClass, so we can still cast it
// to junit.framework.test
junit.framework.Test test2 = (junit.framework.Test) test1;
}
}
正如你在上面看到的,你可以创建一个类,它是org.junit.Testand的子类型junit.framework.Test,所以如果你在两者之间进行转换,编译器不会抱怨。如果您的类没有实现这两个接口,并且您尝试将实例转换为它没有实现的接口,您只会得到一个运行时异常。