void *与id类型的相互转换

本文详细解析了在ARC环境下,Objective-C中void*与id类型转换的正确方式,包括__bridge、__bridge_retained、__bridge_transfer关键字的使用,以及CFBridgingRetain与CFBridgingTransfer函数的作用。

void *与id类型相互转换

在MRC下,void *与id类型相互转换完全没问题。

id obj  = [[NSObject alloc] init];
void *p = (void *)p;
obj = (id)p;

但是在ARC下,这种直接转换编译器会报错,需要使用__bridge关键字:

id obj = [[NSObject alloc] init];  //引用计数为1
void *p  = (__bridge void *)obj; //引用计数仍为1
id obj2 = (__bridge id)p ;// 引用计数为2,因为obj2是__strong

 

__bridge_retained与__bridge_transfer

与__bridge相关的还有另外两个:__bridge_retained和__bridge_transfer。

id obj = [[NSObject alloc] init]; //引用计数为1
void *p = (__bridge_retained void *)obj ;// 引用计数为2


//上述代码等价在MRC为
id obj = [[NSObject alloc] init];
[obj retain];
void *p = (__bridge void)obj
id obj = (__bridge_transfer id)p  //引用计数仍为1


//上述代码等价在MRC为id obj obj = (__bridge id)p
[obj retain];
[(id)p release];

 

CFBridgingRetain与CFBridgingTransfer

这两个函数也只在ARC下生效,等价于:

CFTypeRef CFBridgingRetain(id X) {
    return (__bridge_retained CFTypeRef)X;
}


id CFBridgingRelease(CFTypeRef X) {
     return (__bridge_transfer id)X;
}

 

是的,**MyBatis-Plus 会自动将 Java 中的布尔类型(`boolean` / `Boolean`) MySQL 的 `TINYINT(1)` 类型进行自动转换**,这是基于 MyBatis 的默认行为,并被 MyBatis-Plus 继承和沿用。 --- ## ✅ 一、默认映射规则 | Java 类型 | MySQL 类型 | 存储值(MySQL 中) | 说明 | |----------|------------|------------------|------| | `boolean` / `Boolean` | `TINYINT(1)` | `0` 或 `1` | 推荐方式 | | `boolean` / `Boolean` | `BIT(1)` | `b'0'` 或 `b'1'` | 也可用,但不推荐 | > 🔔 **MyBatis 和 MyBatis-Plus 默认将 `boolean` 映射为 `TINYINT(1)`,其中:** > - `true` → 存为 `1` > - `false` → 存为 `0` --- ## ✅ 二、代码示例 ### 1. 数据库表结构(MySQL) ```sql CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), age INT, deleted TINYINT(1) DEFAULT 0 COMMENT '是否删除: 0=否, 1=是', enabled TINYINT(1) DEFAULT 1 COMMENT '是否启用' ); ``` ### 2. 实体类(Java) ```java @Data @TableName("user") public class User { private Long id; private String name; private Integer age; // 自动映射:数据库 tinyint(1) -> Java boolean private Boolean deleted; private boolean enabled; } ``` ### 3. 使用 MyBatis-Plus 操作 ```java @Service public class UserService { @Autowired private UserMapper userMapper; public void testBoolean() { User user = new User(); user.setName("Alice"); user.setAge(24); user.setDeleted(false); // → 写入数据库为 0 user.setEnabled(true); // → 写入数据库为 1 userMapper.insert(user); // 查询回来也会自动转换 User dbUser = userMapper.selectById(user.getId()); System.out.println(dbUser.isDeleted()); // false System.out.println(dbUser.isEnabled()); // true } } ``` ✅ 插入后数据库中: ```sql SELECT * FROM user; -- id: 1, name: Alice, age: 24, deleted: 0, enabled: 1 ``` --- ## ✅ 三、原理说明 ### MyBatis 默认 TypeHandler MyBatis 提供了内置的 `BooleanTypeHandler`,其逻辑如下: ```java // org.apache.ibatis.type.BooleanTypeHandler public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException { ps.setBoolean(i, parameter); // 底层调用 setInt(i, value ? 1 : 0) } public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException { int value = rs.getInt(columnName); return value != 0; // 0 -> false, 非0 -> true } ``` 所以即使你使用的是 `TINYINT` 而不是 `BOOLEAN`(MySQL 其实没有原生布尔类型),也能正确转换。 --- ## ✅ 四、注意事项 ### ⚠️ 1. 字段必须是 `TINYINT(1)` 或 `TINYINT(N)` - 建议统一用 `TINYINT(1)` 表示布尔值,虽然 `(N)` 也可以。 - 不要用 `VARCHAR('yes/no')` 或 `ENUM`,除非有特殊需求。 ### ⚠️ 2. 查询时注意 null 值处理 如果你使用 `Boolean`(包装类),可能为 `null`;而 `boolean` 基本类型不能为 null,建议根据业务选择。 ```java private Boolean isVip; // 可以为 null(如未设置) private boolean locked; // 必须有值,默认 false ``` ### ⚠️ 3. 数据库迁移工具建议明确注释 ```java /** * 是否已删除:0=未删除,1=已删除 */ @TableField("deleted") private Boolean deleted; ``` --- ## ✅ 五、常见问题解答 ### ❓ Q1:能不能用 `BIT(1)`? 可以,但不如 `TINYINT(1)` 灵活。某些 JDBC 驱动对 `BIT` 支持不好,**推荐使用 `TINYINT(1)`**。 ### ❓ Q2:如果数据库存的是 `2`,Java 会变成 `true` 还是 `false`? → 会变成 `true`!因为 MyBatis 判断规则是: ```java return rs.getInt("enabled") != 0; // 所有非零值都视为 true ``` 所以要确保业务逻辑中只写入 `0` 或 `1`。 --- ## ✅ 总结 | 特性 | 是否支持 | |------|---------| | `boolean` ↔ `TINYINT(1)` 自动转换 | ✅ 支持 | | `true` → 存为 `1` | ✅ | | `false` → 存为 `0` | ✅ | | 支持 `Boolean` 包装类(含 null) | ✅ | | 无需手动配置 TypeHandler | ✅ | > ✅ **结论:你可以放心使用 `boolean` / `Boolean` `TINYINT(1)` 的映射,MyBatis-Plus 完全支持且开箱即用。** ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值