这篇文章的目的是找出如何避免使用匿名内部类。
我没有广泛地使用inner anonymous classes
,但我正试图简化某人的包examples.introduction.novice.simpler.model;
public class Person {
public final String name;
// --- Attribute
public static final Attribute<Person, String> NAME = new SimpleAttribute<Person, String>("name") {
public String getValue(Person person, QueryOptions queryOptions) { return person.name; }
};
}
打开上面的&我重写了它,所以(如果我错了请纠正我):
public class Person {
public final String name;
public Person(String name) {
this.name = name;
}
// TODO: Simplify
// ----------- Attributes -------------
public static final Attribute<Person, String> NAME = new Name<Person, String>("name") ;
}
当然,我创建了Name
类,所以:
public class Name<O, A> extends SimpleAttribute<O, A> {
public Name(String attributeName) {
super(attributeName);
// TODO Auto-generated constructor stub
}
public String getValue(Person person, QueryOptions queryOptions) { return person.name; }
@Override
public A getValue(O arg0, QueryOptions arg1) {
// TODO Auto-generated method stub
return null;
}
}
然而,我得到一个错误,所以:
Exception in thread "main" java.lang.ExceptionInInitializerError
at examples.introduction.novice.simpler.model.Introduction.main(Introduction.java:17)
Caused by: java.lang.IllegalStateException: Attribute 'name' (class examples.introduction.novice.simpler.model.Name) is invalid, cannot read generic type information from it. Attributes should typically EITHER be declared in code with generic type information as a (possibly anonymous) subclass of one of the provided attribute types, OR you can use a constructor of the attribute which allows the types to be specified manually.
at com.googlecode.cqengine.attribute.support.AbstractAttribute.readGenericObjectType(AbstractAttribute.java:139)
at com.googlecode.cqengine.attribute.support.AbstractAttribute.<init>(AbstractAttribute.java:43)
at com.googlecode.cqengine.attribute.SimpleAttribute.<init>(SimpleAttribute.java:55)
at examples.introduction.novice.simpler.model.Name.<init>(Name.java:11)
at examples.introduction.novice.simpler.model.Person.<clinit>(Person.java:23)
... 1 more
回顾一下:我试图在以下包中简化以下示例(这是我试图简化的原始工作示例,它有两个类:主类称为Introduction.java
和伴随的类称为Person.java
):https://github.com/mrarthurwhite/CQEngineIntroExample/tree/master/src/examples/introduction/novice
尝试简化它在下面的包中(它只是试图解包Person.java
类:https://github.com/mrarthurwhite/CQEngineIntroExample/tree/master/src/examples/introduction/novice/simpler/model
与&耐心的读者可以从上面看到,我正试图解包Attribute
的匿名内部类。这是Attribute
类的链接&cqengine
库:https://github.com/npgall/cqengine/blob/master/code/src/main/java/com/googlecode/cqengine/attribute/Attribute.java
下面是Attribute
的子类SimpleAttribute
的链接:https://github.com/npgall/cqengine/blob/master/code/src/main/java/com/googlecode/cqengine/attribute/SimpleAttribute.java
public class Name extends SimpleAttribute<Person, String> {
public Name() {
super("name");
// TODO Auto-generated constructor stub
}
@Override
public String getValue(Person person, QueryOptions queryOptions) {
return person.name;
}
}
试试这个。如果你做一个新的泛型实现,你基本上必须使用反射来获取值。如果你这样做,它会变得更复杂,而不是更简单。
对于您的代码,Java编译器将生成一个更具体的、非泛型的具体类,如下所示(当然名称会有所不同):
public class Name extends SimpleAttribute<Person, String> {
public Name(String attributeName) {
super(attributeName);
}
@Override
public String getValue(Person person, QueryOptions queryOptions) { return person.name; }
}
注意超类的类型是SimpleAttribute<Person, String>
。SimpleAttribute
的类型参数都是具体类型,而不是像你尝试的O
和A
那样的类型变量。
你可以这样使用:
public static final Attribute<Person, String> NAME = new Name("name");
从异常消息判断,
属性'name'(类examples.introduction.novice.simpler.model.Name)无效,无法从中读取泛型类型信息。
您正在使用的库依赖于这种行为(类型参数是具体类型的事实)来读取类型参数。它可能调用了以下内容:
((ParameterizedType)NAME.getClass().getGenericSuperclass()).getActualTypeArguments()
如果SimpleAttribute
的类型参数是O
和A
,就像你试图解包匿名类一样,返回的数组将没有任何真正的类型,这可能就是为什么它说"不能读取泛型类型信息"的原因。
另一方面,如果您使用匿名类(或答案开头的代码),则生成的内部类将以SimpleAttribute<Person, String>
作为超类,库将能够从中读取有用的信息。
还要注意,即使库没有碰巧读取泛型类型参数,您对匿名类的解包仍然不会做与原始代码相同的事情。也就是说,您重写抽象方法的方式:
@Override
public A getValue(O arg0, QueryOptions arg1) {
// TODO Auto-generated method stub
return null;
}
与原始代码中重写抽象方法的方式不同:
public String getValue(Person person, QueryOptions queryOptions) { return person.name; }
您在Name
中定义的getValue
的另一个重载并不真正相关。