为什么JDBC使用原语而不是包装clasess?

ADT*_*DTC 5 java jdbc resultset prepared-statement

这不是我现在遇到的具体问题,只是我无法解决的问题.我在这里找不到任何问题或在网上找到关于此的信息.

诸如java.lang.Integer(对于原语int)的包装类从一开始就存在于Java中.但JDBC的开发人员选择实现诸如getIntgetLong使用Java原语之类的方法.原语的问题在于它们不能代表SQL NULL.

要解决这一问题,JDBC开发者写了很多方法来返回默认的原始值,如0false当列NULL,并推出了wasNull()为用户检查它是否应该是功能null.更糟糕的是,当许多其他方法(如PreparedStatement) setInt接受原语而不是包装器对象时,用户必须有条件地使用setNull来设置相应的列NULL.

我发现这为其用户如何使用JDBC API 增加了不必要的复杂性.如果JDBC的ResultSet对象在列具有SQL时getInteger将Java null作为Integer对象返回NULL,那么在没有检查麻烦的情况下它将非常方便wasNull.Java的拆箱会自动处理必须将Integer对象分配给int原始变量并将其转换为的情况0.如果PreparedStatement有一个setInteger方法,用户可以简单地使用它来设置一个合适的列的值 - 包括一个SQL NULL值 - 而无需检查它是否应该为null并且还原为setNull.

直到现在,JDBC还没有改变以纠正这种异常现象.即使在我们已经处于Java 1.7或1.8之后,JDBC仍继续使用原始类型(我是否正确?).Java的内置装箱和拆箱将确保假定原始类型的旧应用程序将继续正确使用更新的JDBC版本以使用包装器.那么为什么没有人费心去升级JDBC以使用包装器对象代替原语?

PS:听听推荐的JDBC解决这个荒谬问题的替代解决方案会很高兴.

Mar*_*eel 5

虽然它没有完全回答您的问题,但JDBC 1.2规范包含以下"被拒绝"的设计选择:

A.8支持GetObject与getXXX
由于各种get/set方法和通用getObject/setObject方法之间的重叠,我们考虑丢弃get/set方法并简单地使用getObject/setObject.然而,对于程序员知道SQL类型的简单常见情况,结果的转换和提取非常繁琐:
int i = ((Integer)r.getObject(1, java.sql.Types.INTEGER)).intValue()
因此我们决定在这种情况下稍微弯曲我们的极简主义原则并保留各种get/set方法作为首选接口.大多数应用程序编程人员,同时还为工具构建器和复杂的应用程序添加了getObject/setObject方法

该规范的第14章还说:

例如,SQL INTEGER通常映射到Java int.这支持一个简单的接口,用于读取和写入SQL值作为简单的Java类型.

第2章说:

提供与Java系统其余部分一致的Java接口

据我所知,大多数Java API使用原始类型而不是包装类型.

同样在规范的时间(1.2是1997年1月10日),没有拳击和拆箱,使用Integer等是相当麻烦的.例如,您根本无法Integer直接进行数学运算,首先需要调用intValue()获取int之前可以实际执行任何基本操作(如加法,乘法等),然后您需要将结果转换回Integer存储它.对于基元来说,这听起来是一个非常好的理由.

请记住,规范是在1995年到1997年之间的某个地方设计的,这个时代的内存相对更加昂贵,而原语的包装对象只需要花费更多的内存.我相信一个简单的对象是8字节+原始字段的大小.对于int这是12字节而不是4字节的成本.