问题: 我希望能够 在Java中 以通用方式访问 Java对象的
任何属性/字段,就像动态语言(例如Groovy,JavaScript)一样。在编写此管道代码时,我不知道它是什么类型的对象或属性/字段名称是什么。但是当我使用它时,我将知道属性/字段名称。
我当前的解决方案: 到目前为止,我已经编写了一个简单的包装器类,该包装器类java.beans.Introspector
用于获取Bean /
POJO的属性并将其公开为Map<String, Object>
。它很粗糙,但适用于简单的情况。
我的问题 是,除了反射/转换为地图外,还有什么其他方法可用来解决此问题?
在我进一步走这条路之前,我想知道是否有人知道我如何可以从Rhino中吞噬某些东西,或者也许javax.script.*
有一个经过深思熟虑地实现了这一概念的人。也许我没有考虑过一种完全不同的方法。
编辑: 是的,我对反射很熟悉(我相信这是Introspector在后台使用的功能)。我只是好奇是否还有其他经过深思熟虑的解决方案。
编辑2:
看来,最流行的答案包括1)直接或通过助手类进行反射,和/或2)映射到实现所需类成员的接口。谈到利用Groovy的评论我真的很感兴趣。由于Groovy具有真正的鸭子类型并且是JVM语言,是否有一种方法可以在Groovy中创建简单的帮助程序并从Java调用它?这真的很酷,可能更灵活并且性能更好。
答:
我将迈克的答案标记为最佳,因为这是一个最接近的完整概念。对于这种特殊情况,我可能不会走这条路,但这无疑是一种有用的方法。查看此内容的任何人都应该确保阅读此处的对话,因为那里也有很多有用的信息。
谢谢!
如果知道要公开的一组API,例如说您想访问length方法和迭代器方法,则可以定义一个接口:
public interface TheInterfaceIWant {
int length();
void quack();
}
所以你创建一个代理
final Object aDuck = ...;
TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
TheInterfaceIWant.class.getClassLoader(),
new Class[] { TheInterfaceIWant.class },
new InvocationHandler() {
public Object invoke(
Object proxy, Method method, Object[] args)
throws Throwable {
return aDuck.getClass().getMethod(
method.getName(), method.getParameterTypes()).invoke(aDuck, args);
}
});
然后,您可以像使用动态类型语言的鸭子一样使用包装器。
if (aDuckWrapper.length() > 0) {
aDuckWrapper.quack();
}
这是一个全长可运行示例,该示例使用包装程序将“ Quack”打印四次:
import java.lang.reflect.*;
public class Duck {
// The interface we use to access the duck typed object.
public interface TheInterfaceIWant {
int length();
void quack();
}
// The underlying instance that does not implement TheInterfaceIWant!
static final class Foo {
public int length() { return 4; }
public void quack() { System.out.println("Quack"); }
}
public static void main(String[] args) throws Exception {
// Create an instance but cast away all useful type info.
final Object aDuck = new Foo();
TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
TheInterfaceIWant.class.getClassLoader(),
new Class[] { TheInterfaceIWant.class },
new InvocationHandler() {
public Object invoke(
Object proxy, Method method, Object[] args)
throws Throwable {
return aDuck.getClass().getMethod(
method.getName(), method.getParameterTypes()).invoke(aDuck, args);
}
});
for (int n = aDuckWrapper.length(); --n >= 0;) {
// Calling aDuck.quack() here would be invalid since its an Object.
aDuckWrapper.quack();
}
}
}
问题内容: 我最近听说过鸭式打字,并且阅读了有关它的Wikipedia文章,但是我很难将示例转换为Java,这确实有助于我的理解。 谁能给出Java中鸭子类型的清晰示例,以及我将如何使用它? 问题答案: Java设计上不适合鸭子输入。您可能选择这样做的方式是反思: 但是我主张使用一种动态语言(例如Groovy)来实现,在这种语言中,它更有意义: 参考
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。 比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。 又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,
该程序应模拟滚动两个骰子,并计算和。添加一个循环,使程序可以玩10,000个游戏。添加计数器,计算玩家赢了多少次,输了多少次。在10,000场比赛结束时,计算获胜的概率[即赢/(赢+输)]并输出该值。从长远来看,谁会赢得最多的比赛,你还是房子?注意:要生成一个随机数x,其中0x≤<1,使用x=math.random();例如,乘以6并转换为一个整数,结果是一个介于0和5之间的整数。
问题内容: 我正在尝试为需要用户输入的方法创建一些JUnit测试。被测方法看起来类似于以下方法: 有没有一种方法可以自动将程序传递给int而不是我或其他人在JUnit测试方法中手动执行此操作?像模拟用户输入一样? 提前致谢。 问题答案: 你可以通过调用来用自己的流替换可以是一个字节数组: 通过将IN和OUT作为参数传递,不同的方法可以使此方法更具可测试性:
问题内容: 我正在尝试测试从中获取输入的函数,而我目前正在使用类似以下内容进行测试: 以测试自动化的名义,有什么方法可以伪造输入? 问题答案: 简短的答案是猴子补丁 。 这是一个使用a的简单示例,该示例丢弃提示并返回我们想要的内容。 被测系统 测试用例:
本文向大家介绍详细介绍Python的鸭子类型,包括了详细介绍Python的鸭子类型的使用技巧和注意事项,需要的朋友参考一下 鸭子类型基本定义 首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。 以下是维基百科中对鸭子类型得论述: 在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实