类型
- 对于基元类型,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);