编写原生方法

J2ObjC 支持将 Objective-C 嵌入到 Java 原生方法中,这与 GWT 的 JSNI 支持 JavaScript 嵌入的方式非常相似。J2ObjC 嵌入与 GWT 之间的主要区别在于 J2ObjC 使用 /*-[]-*/ 来划分 Objective-C 代码。此功能称为 OCNI(Objective-C 原生接口),旨在与 GWT 的 JSNI 区分开来。

以下是 JRE 模拟库的 java.lang.System 版本中的一个示例:

  public static native long currentTimeMillis() /*-[
    // Use NSDate
    return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
  ]-*/;

J2ObjC 会复制注释(减去分隔符),以创建方法正文:

  + (long long int)currentTimeMillis {
    // Use NSDate
    return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
  }

原生导入

J2ObjC 会扫描正在转换的 Java 代码,以为其依赖项添加 #import 指令,同时导入 Foundation 框架。不过,仅需单独添加原生代码所需的任何导入项。如需添加导入,请在 Java 源文件中的第一个类上方添加一个 OCNI 部分,并在该类中指定导入内容;例如:

  package my.project;

  /*-[
  #import "java/lang/NullPointerException.h"
  ]-*/

  public class Test {
    native void test() /*-[
      @throw [[JavaLangNullPointerException alloc] init];
    ]-*/;
  }

在上面的示例中,导入操作是必要的,因为引用该类型的唯一位置是在原生代码中。

原生块

在类正文中,J2ObjC 会扫描是否存在 OCNI 块。这些块会原封不动地添加到翻译后的文件,且位于与翻译的类成员的相对位置。示例如下:

  /*-[
    static void log(NSString *msg) {
      NSLog(@"%@", msg);
    }
  ]-*/;

此 C 函数可通过在此 OCNI 块之后声明的任何原生方法调用。

此 OCNI 代码块的一个特殊变体会在生成的头文件(而不是 .m 文件中)中插入代码:/*-HEADER[...]

从原生代码调用 Java 方法

public native void bar(JSNIExample x, String s) /*-[
  // Call instance method instanceFoo() on this
  [self instanceFooWithNSString:s];

  // Call instance method instanceFoo() on x
  [x instanceFooWithNSString:s];

  // Call static method staticFoo()
  JSNIExample_staticFooWithNSString_(s);
]-*/;

通过原生代码访问字段

如需读取实例字段,请使用 myInstanceField_self->myInstanceField_。末尾的后缀可避免与同名方法发生冲突。

请注意,具有预留名称的字段将带有两个下划线。例如,名为“id”的字段在 Java 中是合法的,但在 Objective C 中则不然。翻译后,该字段将命名为“id__”。因此,请检查生成的文件是否存在“无此类字段”编译器错误。

如需写入对象实例字段,请使用 JSNIExample_set_myInstanceField(string)

读取静态字段:JSNIExample_get_myStaticField()

写入静态字段:JSNIExample_set_myStaticField(value)

J2ObjC 和 GWT

选择了不同的分隔符,以便在下一个 J2ObjC 版本中忽略 GWT JSNI 注释(之前使用的是与 GWT 相同的分隔符)。这意味着单个 Java 源代码可以具有具有 Objective-C、GWT 和 Android(通过 JNI)实现的原生方法:

  static native void log(String text) /*-{ // left-brace for JavaScript
    console.log(text);
  }-*/ /*-[                                // left-bracket for Objective-C
     NSLog(@"%@", text);
  ]-*/;

J2ObjC 和 Android

J2ObjC 和 Android 原生方法实现“照常运行”,因为 Android 原生方法在单独的 JNI C 或 C++ 文件中实现。当针对 Android 或任何其他 Java 平台的 javac 编译时,Java 类中的所有 OCNI 注释都会被移除。