Java本地方法。公共 vs. 私有

12

假设我们需要在本地代码中实现一些Java方法并将其暴露给用户。 我们知道所有的工作都由本地端完成,即Java代码的唯一责任是将用户提供的参数传递给本地代码并返回结果。 根据这一点,可以使用两种方式实现Java层:

  • 通过直接向用户公开的本机方法:

  • public native Object doSmth(Object arg0, Object arg1);
    
    通过在私有本地方法周围使用轻量级的公共包装器:
    public Object doSmth(Object arg0, Object arg1) {
        return nativeDoSmth(arg0, arg1);
    }
    
    private native Object nativeDoSmth(Object arg0, Object arg1);
    

    我在实际项目中看到了这两种方法,甚至有些项目中都同时使用前一种和后一种方法。

    那么,我的问题是:这两种提到的方法中是否有任何技术、性能或可维护性优势,应该鼓励只使用一个变体。或者说,这完全只是个人喜好的问题?


6
一个public方法是对象API的一部分。一个native方法是实现决策。实现细节不应该对公共API可见。选项2从API中隐藏了实现细节。 - Andreas
1
你会发现选项2在JDK中是独家使用的,而不是选项1。我认为这是一个好主意,它在设计和维护JNI层时给了你另一个自由度。 - user207421
你的问题假设签名是相同的。然而,在JNI代码中,类API自然的方式往往不同,因此签名也会不同。在许多情况下,使用Java将输入和输出转换为更易于在JNI中处理的数据类型会更简单。 - Tom Blodget
2个回答

5
所以我的问题是:在提到的这些替代方案中,是否有任何技术、性能或可维护性上的优势,应该鼓励只使用一个变体。
可维护性优势是关键。如评论所述,对象公开其行为,实现方式并不是用户需要了解的。这使得您具有更大的灵活性。
假设将来(参见:可维护性),您发现您想/需要调整方法,使其在调用本机之前和/或之后执行某些操作。在第一种方法中,您需要弃用该方法并创建一个新方法。在第二种方法中,您只需在方法中添加所需内容,而用户则无需关心。
至于性能,在理论上,第一种方法更快,因为它少了1个调用。但在实践中,这完全可以忽略不计。

不需要弃用该方法,因为您可以在没有任何客户端代码注意到的情况下从第一种变体简单地切换到第二种。因此,在真正需要之前没有必要使用第二种。当然,这将需要重新编译本地代码,但这应该在您的控制范围内。 - Holger
@Holger 我不明白。在第一种方法中,您想要对本地代码进行更改吗?如果您使用第二种方法,您将在Java端进行相同的更改? - user1803551
不需要。当需要在Java端装饰方法时,您只需将变体1更改为变体2,即可获得第二个变体的所有好处。由于“native”方法的名称在两个变体中不同,因此需要调整本机代码的名称,或创建一个新名称的委托。在任何情况下,本机代码都需要重新编译,但不需要进行重大更改。 - Holger

2

我认为这主要是个人风格选择。如果您考虑以下代码:

rattias-macbookpro:tst rattias $ diff Test1.cl Test1.class rattias-macbookpro:tst rattias $ vi Test1.java

public class Test1 {
  public static void main(String[] args) {
    Test2 t = new Test2();
    t.m();
  }
}

public class Test2 {
  public native void m();
}

编译这个程序会生成一个名为Test1.class的文件,该文件与以下定义的Test2所生成的文件完全相同:
public class Test2 {
  public void m() {
  }
}  

这意味着您可以在任何时候更改实现为本地、纯Java或纯Java包装器到本地私有方法,而不影响用户。可能会有一个问题,即整个公共API函数是否需要是本地的,还是只是计算的一部分,但这也可以在任何时候更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接