翻译参考

类型

  • 对于基元类型,J2ObjC 定义了 JNI 样式的类型定义符。
  • 对于典型的类类型,软件包采用驼峰式大小写形式并置于类名称前面。
  • 对于基本对象类型和所有类型变量,使用“id”。
  • 一些核心 Java 类型会映射到基础类型。(例如,从字符串转换为 NSString)
  • 对于声明为“volatile”的字段,J2ObjC 具有更多使用 C11 _Atomic(...) 类型的类型定义符。
  • 对于内部类型,内部类名称会附加到外部名称,并以下划线结尾。
Java 类型 Objective-C 类型 Objective-C 易变类型
布尔值 jBoolean volatile_jboolean
char jchar volatile_jchar
byte 字节 volatile_jbyte
短片 JShort volatile_jshort
int jint volatile_jint
long Jlong volatile_jlong
float Jfloat volatile_jfloat
双精度 jdouble volatile_jdouble
java.lang.Object id volatile_id
类型变量 id volatile_id
java.lang.String 中 NS 字符串* volatile_id
java.lang.Number 中 NS 编号* volatile_id
java.lang.Cloneable 中 NS 复制* volatile_id
foo.bar.Mumble FooBarMumble* volatile_id
foo.bar.Mumber$Internal FooBarMumble_Inner* volatile_id

方法

Objective-C 方法与 Java 方法有两点重要区别。它们的语法不同,它们会嵌入方法选择器的各个组件之间的参数。Objective-C 方法不支持像 Java 那样的过载。这些差异是通过将参数类型嵌入到生成的选择器中来解决的。这是为了防止过载 Java 方法之间的名称冲突。

生成的 API 有三种不同的 Java 方法:实例方法、静态方法和构造函数。实例方法转换为 Objective-C 实例方法。静态方法和构造函数可转换为 C 样式的函数,但还应添加 Objective-C 封装容器,以便为 Objective-C 开发者提供更熟悉的 API。

实例方法

方法名称的生成方式如下:

  • 零参数方法保持不变
  • 一个或多个参数使用以下模式:
    • <java name>With<1st param keyword>:with<2nd param keyword>:with<3rd param keyword>:
  • 参数关键字规则:
    • 对于基元类型,关键字是 Java 基元的大写名称。(例如,“Char”)
    • 对于非基元类型,关键字是采用驼峰式大小写的完全限定类型名称。(例如,“ComGoogleFoo”)
    • 对于数组类型,“Array”会附加到元素类型的关键字。
Java 示例
interface Foo {
  void bar();
  String bar(int i);
  java.util.List bar(String s, long[] l);
}
Objective-C 示例
- (void)bar;

- (NSString *)barWithInt:(jint)i;

- (id<JavaUtilList>)barWithNSString:(NSString *)s
                      withLongArray:(IOSLongArray *)l;

静态方法

添加 Objective-C 类方法时,应遵循与实例方法相同的命名规则。

使用以下命名规则添加了 C 样式的函数:

  • 从生成的 Objective-C 选择器开始。(例如,barWithInt:)
  • 将冒号替换为下划线。(例如,barWithInt_)
  • 添加类名称,并用下划线分隔。(例如,ComGoogleFoo_barWithInt_)
Java 示例
package com.google;
class Foo {
  static boolean bar() { ... }
  static double bar(int[] i) { ... }
  static void bar(String s, boolean b) { ... }
}
Objective-C 示例
@interface Foo : NSObject

+ (jboolean)bar;

+ (jdouble)barWithIntArray:(IOSIntArray *)i;

+ (void)barWithNSString:(NSString *)s
            withBoolean:(jboolean)b;

@end

FOUNDATION_EXPORT jboolean ComGoogleFoo_bar();

FOUNDATION_EXPORT jdouble ComGoogleFoo_barWithIntArray_(IOSIntArray *i);

FOUNDATION_EXPORT void ComGoogleFoo_barWithNSString_withBoolean_(NSString *s, jboolean b);

构造函数

按照 Objective-C 惯例,添加了 init 实例方法。如果构造函数有参数,则使用与实例方法相同的命名规则。

添加了三个 C 样式的函数:

  • 第一个函数接受新分配的对象作为其第一个参数。此函数通常用于从子类构造函数进行调用。这遵循与静态方法相同的命名规则。(其中,“init”是方法名称)
  • 添加了两个函数,用于分配和初始化新对象。它们通过其前缀来区分:
    • create_ 函数将返回自动释放的对象。
    • new_ 函数将返回保留的对象。
Java 示例
package com.google;
class Foo {
  Foo() { ... }
  Foo(Object a, Object b) { ... }
}
Objective-C 示例
@interface ComGoogleFoo : NSObject

- (instancetype)init;

- (instancetype)initWithId:(id)a
                    withId:(id)b;

@end

FOUNDATION_EXPORT void ComGoogleFoo_init(ComGoogleFoo *self);

FOUNDATION_EXPORT ComGoogleFoo *new_ComGoogleFoo_init() NS_RETURNS_RETAINED;

FOUNDATION_EXPORT ComGoogleFoo *create_ComGoogleFoo_init();

FOUNDATION_EXPORT void ComGoogleFoo_initWithId_withId_(ComGoogleFoo *self, id a, id b);

FOUNDATION_EXPORT ComGoogleFoo *new_ComGoogleFoo_initWithId_withId_(id a, id b) NS_RETURNS_RETAINED;

FOUNDATION_EXPORT ComGoogleFoo *create_ComGoogleFoo_initWithId_withId_(id a, id b);

字段

实例字段(非静态)

Java 实例变量转换为 Objective-C 实例变量。该名称与末尾带有下划线的名称相同。声明为“final”的原始字段是一种特殊情况,不会转换为实例变量。

  • 可以使用“->”语法直接访问字段。
  • 原初字段可以直接设置。
    • 最终基元(常量)与静态常量类似。(请参阅静态字段
  • 必须使用提供的 setter 函数设置非基元字段:
    • ClassName_set_fieldName_(instance, value)
Java 示例
package com.google;
class Foo {
  public int myInt;
  public String myString;
}
Objective-C 示例
Foo *foo = [[Foo alloc] init];

// Access a primitive field.
i = foo->myInt_;

// Set a primitive field.
foo->myInt_ = 5;

// Access a non-primitive field.
NSString *s = foo->myString_;

// Set a non-primitive field.
ComGoogleFoo_set_myString_(foo, @"bar");

静态字段

必须使用提供的 getter 和 setter 函数访问静态变量。这些访问器函数可确保类访问是在访问变量之前发生的。

  • 访问静态字段
    • ClassName_get_fieldName()
  • 分配(非最终)静态字段
    • ClassName_set_fieldName()
  • 获取指向原始静态字段的指针
    • ClassName_getRef_fieldName()
    • 仅适用于非最终字段和非易失性字段。

最终基元字段(常量)可以安全地访问,因为它们的值不依赖于类初始化。

  • ClassName_fieldName
Java 示例
package com.google;
class Foo {
  public static final MY_FINAL_INT = 5;
  public static int myInt;
  public static String myString;
}
Objective-C 示例
// Access a primitive constant field.
jint i = ComGoogleFoo_MY_FINAL_INT;   // No class initialization
i = ComGoogleFoo_get_MY_FINAL_INT();  // Class initialization

// Access a primitive field.
i = ComGoogleFoo_get_myInt();

// Set a primitive field.
ComGoogleFoo_set_myInt(5);

// Access a non-primitive field.
NSString *s = ComGoogleFoo_get_myString();

// Set a non-primitive field.
ComGoogleFoo_set_myString(@"bar");

枚举

J2ObjC 会为每个 Java 枚举生成两种类型。系统会生成一个 Objective-C 类类型,该类可提供 Java 枚举的完整功能。此外,系统会使用 Foundation 框架的 NS_ENUM 宏生成 C 枚举。所有生成的 API 都使用 Objective-C 类类型。C 枚举可用作 Switch 语句的常量值或存储类型。

生成的枚举类型的名称如下所示:

  • Objective-C 类使用与常规 Java 类相同的规则命名。(请参阅类型
  • C 枚举会命名为一个常规 Java 类,并带有“_Enum”后缀。

访问枚举常量的方式与访问静态字段类似。

Java 示例
package com.google;
enum Color {
  RED, GREEN, BLUE
}
Objective-C 标头示例
typedef NS_ENUM(NSUInteger, ComGoogleColor_Enum) {
  ComGoogleColor_Enum_RED = 0;
  ComGoogleColor_Enum_GREEN = 1;
  ComGoogleColor_Enum_BLUE = 2;
};

@interface ComGoogleColor : JavaLangEnum < NSCopying >
+ (IOSObjectArray *)values;
+ (ComGoogleColor *)valueOfWithNSString:(NSString *)name;
@end

inline ComGoogleColor *ComGoogleColor_get_RED();
inline ComGoogleColor *ComGoogleColor_get_GREEN();
inline ComGoogleColor *ComGoogleColor_get_BLUE();

// Provides conversion from ComGoogleColor_Enum values.
FOUNDATION_EXPORT ComGoogleColor *ComGoogleColor_fromOrdinal(NSUInteger ordinal);