在处理具有多个构造函数的 Java 类时发现 pyjnius 的错误。
当我执行下面的 Java 代码时,main 方法将调用第二个构造函数并优雅地完成。
当我执行下面的python代码时,它会报告未找到构造函数。
(jnius.JavaException: No constructor matching your arguments, available: ['(ILjava/lang/String;)V', '(ILjava/lang/String;Ljava/lang/Object;[I)V'])
但是当我删除 java 代码中的第一个构造函数时,我使用 pyjnius 的 python 代码可以正确地找到唯一的构造函数并优雅地完成。
Java类
public class SampleJavaClass {
public SampleJavaClass( int arg1, String arg2, int arg3, Object arg4, int... arg5 ) {
System.out.println("arg1: " + Integer.toString(arg1));
System.out.println("arg2: " + arg2);
System.out.println("arg3: " + arg3);
System.out.println("arg3: " + arg4);
System.out.println("arg4: " + arg5.toString());
}
// the constructor plans to use
public SampleJavaClass (int arg1, String arg2, Object arg3, int... arg4) {
System.out.println("arg1: " + Integer.toString(arg1));
System.out.println("arg2: " + arg2);
System.out.println("arg3: " + arg3);
System.out.println("arg4: " + arg4.toString());
}
public static void main(String[] args) {
SampleJavaClass test = new SampleJavaClass(1, "var2", null, 4);
}
}
带有 pyjnius 的 Python 代码
import os
currentPath = os.getcwd()
classpath = currentPath + "/SampleJavaClass.class"
import jnius_config
jnius_config.set_classpath('.', classpath)
from jnius import autoclass
def main():
SampleJavaClass = autoclass("SampleJavaClass")
SampleJavaClass(1, "var2", None, 4)
print("Execution finished!")
if __name__ == "__main__":
main()
当 pyjnius 调用方法或构造函数时,它首先检查是否有 0、1 或多个具有给定名称的构造函数或方法。 如果只有 1,它总是会打电话,希望最好。 如果有多个,它会执行此评分过程以尝试确定每个是否可接受。 希望只有一个是可以接受的; 如果没有,它会抛出一个错误。
在这种情况下,它拒绝两者,因为构造函数是不可接受的。 使用签名提示可以通过跳过评分过程来解决问题。 签名提示是一个很好的解决方法。
对于这个问题,我仔细查看了代码,发现实际上存在导致此问题失败的错误。 很高兴这是一个简单的修复。 稍后我将通过单元测试进行 PR。
您是否尝试过使用构造函数签名提示?
看
举个例子。
我刚刚尝试添加一个签名,如下面的代码所示,但它发出了断言错误。 我哪里搞砸了?
错误
File "jnius/jnius_export_class.pxi", line 270, in jnius.JavaClass.__init__
File "jnius/jnius_export_class.pxi", line 319, in jnius.JavaClass.call_constructor
AssertionError
带有 pyjnius 的 Python 代码
import os
currentPath = os.getcwd()
classpath = currentPath + "/SampleJavaClass.class"
import jnius_config
jnius_config.set_classpath('.', classpath)
from jnius import autoclass
def main():
SampleJavaClass = autoclass("SampleJavaClass")
SampleJavaClass(1, "var2", None, 4, signature="(ILjava/lang/String;Ljava/lang/Object;[I)V")
print("Execution finished!")
if __name__ == "__main__":
main()
这是相关的代码:
requestedDefn = kwargs.pop('signature', None)
for definition, is_varargs in definitions:
found_definitions.append(definition)
d_ret, d_args = parse_definition(definition)
if requestedDefn == definition:
assert not is_varargs
scores=[]
score=1
scores.append((score, definition, d_ret, d_args, args))
break
为什么签名提示不能与可变参数一起使用?
没关系,我想通了并对此进行了修复。 我会把它添加到 PR 中。
@enjoybeta我在 PR 中修复了这个问题,但最重要的是,签名提示解决方法在当前版本中不起作用。
@cmacdonald ,他们可以在这里使用另一种解决方法吗?
我的头顶什么都没有 - 添加一个调用 varargs 构造函数的快速 Java 工厂类?
无论如何,我建议我们可以关闭该问题,因为下一个 Jnius 版本将修复该错误。
好主意! 如果可以选择更改源代码,则工厂方法可以处理它。 如果没有,他们可以创建一个单独的 helper-utility 类来为他们做这件事。
同意,我们现在可以关闭这个问题。
最有用的评论
当 pyjnius 调用方法或构造函数时,它首先检查是否有 0、1 或多个具有给定名称的构造函数或方法。 如果只有 1,它总是会打电话,希望最好。 如果有多个,它会执行此评分过程以尝试确定每个是否可接受。 希望只有一个是可以接受的; 如果没有,它会抛出一个错误。
在这种情况下,它拒绝两者,因为构造函数是不可接受的。 使用签名提示可以通过跳过评分过程来解决问题。 签名提示是一个很好的解决方法。
对于这个问题,我仔细查看了代码,发现实际上存在导致此问题失败的错误。 很高兴这是一个简单的修复。 稍后我将通过单元测试进行 PR。