我想在Map
中按其类存储属性,即映射应该只包含任何运行时类型的一个对象。已经有一个当前的实现(它是一个现有的项目),并且该机制是用Map<String, Object>
实现的。
当前实现:
import com.foo.IConfiguration;
public class ClientCode {
private Options options = new Options();
public void putMethod() {
options.subOptions(new IConfiguration() {
public void configure() {}
});
}
public Object getMethod() {
return options.getSubOption(IConfiguration.class);
}
}
public class Options {
private Map<String, Object> map = new HashMap<>();
public void subOptions(Object subOptionsValue) {
if (subOptionsValue != null) {
map.put(subOptionsValue.getClass().getName(), subOptionsValue);
}
}
public Object getSubOption(Class<?> subOptionsClass) {
return subOptionsClass == null ? null : map.get(subOptionsClass.getName());
}
}
然而,对于匿名类,这并不像我想的那样工作。在这种情况下,getName()
和相关方法将放置Options$1
或类似的东西,而我需要它来放置com.foo.IConfiguration
,以便我可以在我的getMethod()中可靠地使用它。
我已经查看了java.lang.Class
的API,但我找不到任何可以指向com.foo.IConfiguration
定义的东西。好吧,我可以,但它不是万无一失:clazz.getInterfaces()
给出了一个接口数组,这在这里很好,但我也可以创建一个new Object() {}
或一个局部类,或一个常规的公共类。
那么是否有一种体面的方法来明确地检索接口或匿名类的超类的FQDN ?
匿名类没有可以依赖的完全限定名,但是可以通过ob.getClass().isAnonymousClass()
检查对象是否为匿名类。然后,只有当超类或超接口返回true时,才能检索它。
您至少应该考虑处理lambdas,即使您还不打算在Java 8上运行它。
正如对biziclop建议的评论中所承诺的那样,我正在提交我使用的代码。这似乎对常规类和匿名类都有效,无论它们是实现接口还是扩展超类。
public void subOptions(Object subOptionsValue) {
if (subOptionsValue != null) {
Class<?> clazz = subOptionsValue.getClass();
String clazzName;
if (clazz.isAnonymousClass()) {
// not sure if getInterfaces can return null
if (clazz.getInterfaces() != null && clazz.getInterfaces().length > 0) {
// anonymous classes can implement only one interface
clazzName = clazz.getInterfaces()[0].getName();
} else {
clazzName = clazz.getSuperclass().getName();
}
} else {
clazzName = clazz.getName();
}
map.put(clazzName, subOptionsValue);
}
}
编辑:处理lambda更困难,因为没有明确的方法来单独列出lambda实现,但我们可以通过以下方式获得足够接近(至少对于我的目的)如何正确确定对象是lambda?和改变
if (clazz.isAnonymousClass()) {...}
if (clazz.isAnonymousClass() || clazz.isSynthetic()) {...}
我建议你把对象的所有接口、基类、接口的超接口等等都放到map中。
例如
interface I1 {}
interface I2 extends I1 {}
class C1 {}
class C2 extends C1 implements I2{}
将C2
的实例放入Options
您可能希望通过I1.class
或C1.class
检索它
但是在这种情况下,如果你有两个类实现一个接口,你需要准备好可能的歧义。
对于这种情况,您可能希望能够显式指定可用于检索特定类的类和接口列表。