我尝试为Java字节码实现几个静态分析.他们试图计算某个方法是否具有特定属性,例如是工厂方法.因为这些分析很难测试,所以我决定编写一些Java代码并使用正确的属性直接注释方法.运行分析后,很容易自动检查计算属性和带注释的属性是否相同.
MyAnnotation:
@Retention(RUNTIME)
@Target(METHOD)
public @interface FactoryMethodProperty {
FactoryMethodKeys value() default FactoryMethodKeys.NonFactoryMethod;
}
Run Code Online (Sandbox Code Playgroud)
示例测试代码:
public class PublicFactoryMethod {
private PublicFactoryMethod(){
// I'm private
}
@FactoryMethodProperty
public static void newInstanceAfterOtherConstructorCall(){
new TransFacoryMethod();
new PublicFactoryMethod();
}
@FactoryMethodProperty(FactoryMethodKeys.IsFactoryMethod)
public static PublicFactoryMethod newInstance(){
return new PublicFactoryMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
因为我的测试代码中的大多数方法都不是工厂方法,所以我将默认设置为枚举值"FactoryMethodKeys.NonFactoryMethod".但是当我没有将枚举值显式传递给注释时,它不会被编译为字节码.
字节码:
#23 = Utf8 value
#24 = Utf8 Lorg/opalj/fpa/test/annotations/FactoryMethodKeys;
#25 = Utf8 IsFactoryMethod
{
public static void newInstanceAfterOtherConstructorCall();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
0: #16()
Code:
stack=1, locals=0, args_size=0
0: new #17 // class …Run Code Online (Sandbox Code Playgroud) 在查看Java的Collection类(OpenJDK 8_update40)之后,我发现了以下方法:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;
}
Run Code Online (Sandbox Code Playgroud)
我不完全理解这里使用泛型类型.据我所知,T是Object的子类型,它也必须实现Comparable接口,该接口也通过泛型参数进行参数化.可比状态的参数必须是T的一些超类型.由于我们有某种递归类型定义.
但这是我的问题:据我所知,Java中的每个类型都是Object的子类型,那么他们为什么要在T的定义中指定它呢?
据我了解,Java枚举不可扩展.所以我想知道为什么枚举不是最终的定义.只是为了确保我理解我在JLS 8中查看的所有内容并找到以下内容:
枚举声明是隐式最终的,除非它包含至少一个具有类主体的枚举常量(第8.9.1节).
这是否意味着我可以创建一个可扩展的枚举常量,例如,自己的方法声明,字段,静态或对象初始化程序?
到目前为止,我没有找到一种方法可以让我得出结论,即枚举可能总是隐含最终的.我哪里错了?