0

我今天在 jython 中使用 java 对象遇到了一个问题,因为 jython 试图变得智能并自动为(简单)getter/setter 方法创建属性 - 对于每个方法,创建一个带有前导get/set删除和下一个字母转换为小写的字段:

//java code
class MyClass {
    public List<Thing> getAllThings() { ... }
    public List<Thing> getSpecificThings(String filter) { ... }
    public void setSomeThing(SomeThing x) { ... }
    [...]
}

#jython code
obj = MyClass()
hasattr(obj, "allThings") #-> True
hasattr(obj, "specificThings") #-> False because getSpecificThings has a param
hasattr(obj, "someThing") #-> False BUT
"someThing" in dir(obj)   #-> True

最后一行在这里总结了我的问题 - 的结果dir包含这些字段(即使在obj.class而不是执行时obj)。我需要一个可在对象上调用的所有方法的列表,对于我的对象来说,这基本上是dir没有这些属性的结果,并且经过过滤以排除继承自的所有内容java.lang.Object以及以下划线开头的内容(这样做的目的是自动将一些 python 类转换为java 等价物,例如地图的字典)。理论上我可以使用__dict__which 不包含它们,但这意味着我也必须递归地评估基类__dict__,我想避免这种情况。我目前正在做的是查看属性是否确实存在,然后检查它是否有argslist属性(意味着它是一个方法),dir除了生成的属性之外的每个条目都是如此:

for entry in dir(obj):
    #skip things starting with an underscore or inherited from Object
    if entry.startswith("_") or entry in dir(java.lang.Object): continue
    #check if the dir entry is a fake setter property
    if not hasattr(obj, entry): continue
    #check if the dir entry has an argslist attribute (false for getter props)
    e = getattr(obj, entry)
    if not hasattr(e, "argslist"): continue
    #start actual processing of the entry...

这种方法的问题在于,所讨论的对象是 bean 的接口,而 getSomething 方法通常从数据库中获取数据,因此对getattr属性的调用会往返于数据库,这可能需要几秒钟并浪费大量内存。

我可以阻止 jython 生成这些属性吗?如果没有,是否有人知道如何在不先访问它们的情况下过滤掉这些属性?我唯一能想到的就是检查是否dir包含一个名为get/的方法set<property>,但这看起来很骇人,并且可能会产生误报,必须避免这种情况。

4

1 回答 1

0

答案比预期的要容易。虽然hasattr属性的aTrue用于对象实例,但False如果所讨论的 get 方法不是静态的,则它用于对象类 - 该类没有该属性,因为您无法在其上执行该方法。更新后的循环现在看起来像这样:

for entry in dir(obj):
    #skip things starting with an underscore or inherited from Object
    if entry.startswith("_") or entry in dir(java.lang.Object): continue
    #check if the dir entry is a fake property
    if not hasattr(obj.class, entry): continue
    #check if the dir entry has an argslist attribute (false if not a method)
    e = getattr(obj, entry)
    if not hasattr(e, "argslist"): continue
    #start actual processing of the entry...
于 2012-10-12T11:43:41.983 回答