匿名的原始 FQDN class
Original FQDN of anonymous class
我想通过 class 将属性存储在 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());
}
}
但是,这对匿名 classes 不起作用。在这种情况下,getName()
和相关方法将放置 Options
或类似的东西,而我需要它放置 com.foo.IConfiguration
以便我可以在我的 getMethod().[=21 中可靠地使用它=]
我查看了 API 中的 java.lang.Class
,但我找不到任何可以让我回到 com.foo.IConfiguration
定义的内容。好吧,我可以,但这不是万无一失的:clazz.getInterfaces()
给出了一个接口数组,这在这里很好,但我也可以创建一个 new Object() {}
或本地 class,或一个常规 public class.
那么有没有一种合适的方法来明确地检索接口的 FQDN 或匿名 class 的超级class?
匿名 classes 没有您可以依赖的完全限定名称,但您可以通过 ob.getClass().isAnonymousClass()
检查对象是否是匿名 class。仅当 returns 为真时,您才可以检索 superclass 或超级接口。
您至少还应该考虑处理 lambda,即使您不打算 运行 在 Java 8 上执行此操作。
我建议你将对象的所有接口、基础 classes 和它的接口的超接口等多次放入映射中。
例如你有
interface I1 {}
interface I2 extends I1 {}
class C1 {}
class C2 extends C1 implements I2{}
并且您将 C2
的实例放入 Options
您可能希望通过 I1.class
或 C1.class
检索它
但是在这种情况下,如果您有两个实现一个接口的 class 实体,则您需要为可能出现的歧义做好准备。
对于这种情况,您可能希望能够明确指定 classes 列表和可用于检索特定 class.
的接口
正如对 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 实现,但我们可以通过遵循 How to correctly determine that an object is a lambda? 和更改
来获得足够接近(至少对于我的目的)
if (clazz.isAnonymousClass()) {...}
到
if (clazz.isAnonymousClass() || clazz.isSynthetic()) {...}
我想通过 class 将属性存储在 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());
}
}
但是,这对匿名 classes 不起作用。在这种情况下,getName()
和相关方法将放置 Options
或类似的东西,而我需要它放置 com.foo.IConfiguration
以便我可以在我的 getMethod().[=21 中可靠地使用它=]
我查看了 API 中的 java.lang.Class
,但我找不到任何可以让我回到 com.foo.IConfiguration
定义的内容。好吧,我可以,但这不是万无一失的:clazz.getInterfaces()
给出了一个接口数组,这在这里很好,但我也可以创建一个 new Object() {}
或本地 class,或一个常规 public class.
那么有没有一种合适的方法来明确地检索接口的 FQDN 或匿名 class 的超级class?
匿名 classes 没有您可以依赖的完全限定名称,但您可以通过 ob.getClass().isAnonymousClass()
检查对象是否是匿名 class。仅当 returns 为真时,您才可以检索 superclass 或超级接口。
您至少还应该考虑处理 lambda,即使您不打算 运行 在 Java 8 上执行此操作。
我建议你将对象的所有接口、基础 classes 和它的接口的超接口等多次放入映射中。
例如你有
interface I1 {}
interface I2 extends I1 {}
class C1 {}
class C2 extends C1 implements I2{}
并且您将 C2
的实例放入 Options
您可能希望通过 I1.class
或 C1.class
但是在这种情况下,如果您有两个实现一个接口的 class 实体,则您需要为可能出现的歧义做好准备。
对于这种情况,您可能希望能够明确指定 classes 列表和可用于检索特定 class.
的接口正如对 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 实现,但我们可以通过遵循 How to correctly determine that an object is a lambda? 和更改
来获得足够接近(至少对于我的目的)if (clazz.isAnonymousClass()) {...}
到
if (clazz.isAnonymousClass() || clazz.isSynthetic()) {...}