Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does JDBC use primitives instead of wrapper clasess? [closed]

This isn't a specific problem I'm having now, just something I can't wrap my head around. I couldn't find any questions here or info on the internet about this.

Wrapper classes such as java.lang.Integer (for the primitive int) have existed in Java since the start. But the developers of JDBC chose to implement methods such as getInt and getLong using Java primitives. The problem with primitives is that they cannot represent SQL NULL.

To workaround this problem, JDBC developers wrote many methods to return default primitive values such as 0 and false when the column is NULL, and introduced a wasNull() function for users to check if it was supposed to be null. What's worse is when many other methods such as PreparedStatement's setInt accept primitives instead of wrapper objects, and users have to conditionally use setNull to set the corresponding column to NULL.

I find that this has added unnecessary complexity to how the JDBC API is to be used by its users. If JDBC's ResultSet object had getInteger returning Java null as an Integer object when the column had SQL NULL, it would have been very convenient without the hassle of checking wasNull. Java's unboxing would automatically take care of cases where the Integer object has to be assigned to an int primitive variable, converting it to 0. If PreparedStatement has a setInteger method, the users can simply use this to set the value for a suitable column - including an SQL NULL value - without the hassle of checking whether it should be null and reverting to setNull.

Even until now, there was no change made to the JDBC to correct this anomaly. JDBC continues to use primitive types even after we are already at Java 1.7 or 1.8 (Am I right?). Java's built-in boxing and unboxing would have ensured that old applications written assuming primitive types would continue to work correctly with a version of JDBC updated to use wrappers. So why has no one bothered to upgrade the JDBC to use wrapper objects in place of primitives?

PS: It would be nice to hear recommended alternative solutions to this nonsensical problem with JDBC.

like image 718
ADTC Avatar asked Aug 12 '13 11:08

ADTC


People also ask

Which is better primitive or wrapper class in Java?

Generally, choose primitive types over wrapper classes unless using a wrapper class is necessary. Primitive Types will never be slower than Wrapper Objects, however Wrapper Objects have the advantage of being able to be null.

What is the difference between wrapper class and primitive?

Wrapper class creates an object and primitive does not create object. Wrapper classes are used with Collections to represent type. Wrappers have methods and can hold memory address/null and primitives hold default values. Primitives are fast compare to wrapper classes as there is no overhead of methods or object.

Why do you think Java provides both primitive data types and wrapper classes for them?

Since primitive types can't directly be coerced into Object references, they are stored in wrapper classes to allow them to be used where Object references are required.

Why does Java use primitive data types?

Objects are much more heavyweight than primitive types, so primitive types are much more efficient than instances of wrapper classes. Primitive types are very simple: for example an int is 32 bits and takes up exactly 32 bits in memory, and can be manipulated directly.


2 Answers

Although it doesn't entirely answer your question, the JDBC 1.2 specification contains the following 'rejected' design choice:

A.8 Support for GetObject versus getXXX
Because of the overlap between the various get/set methods and the generic getObject/setObject methods we looked at discarding our get/set methods and simply using getObject/setObject. However for the simple common cases where a programmer know the SQL types, the resulting casts and extracts are extremely tedious:
int i = ((Integer)r.getObject(1, java.sql.Types.INTEGER)).intValue()
We therefore decided to bend our minimalist principles a little in this case and retain the various get/set methods as the preferred interface for the majority of applications programmers, while also adding the getObject/setObject methods for tool builders and sophisticated applications

Chapter 14 of that spec also says:

For example, a SQL INTEGER is normally mapped to a Java int. This supports a simple interface for reading and writing SQL values as simple Java types.

And Chapter 2 says:

Provide a Java interface that is consistent with the rest of the Java system

And as far as I can tell most of the Java API uses primitive types instead of the wrapper types.

Also around the time of the spec (1.2 is dated January 10, 1997), there was no boxing and unboxing, and using Integer etc was rather cumbersome. For example you simply can't do math with Integer directly, you first need to call intValue() to obtain an int before you can actually do any basic operation like addition, multiplication etc, and then you would need to convert the result back to an Integer to store it. That sounds like a very good reason to have getters and setters for the primitives.

And please remember the spec was designed somewhere between 1995 and 1997, an era where memory was relatively more expensive and wrapper objects for primitives simply cost more memory. I believe a simple object is 8 bytes + the size of the primitive field. For an int that is a cost of 12 bytes instead of 4.

like image 186
Mark Rotteveel Avatar answered Oct 19 '22 17:10

Mark Rotteveel


In a word - compatability. The JDBC API was published long before autoboxing and changing it now would require all 3rd party vendors to update and release their JDBC implementations - a logistical nightmare, if it were even possible plus those using the JDBC API would have to accomodate any changes in behaviour.

The obvious way to make a change of this type would be to release a new API, JDBC2 if you will, though IMHO JDBC is so broken as to warrant this, especially given that JPA/Hibernate hides the low level JDBC API in most common usages.

like image 39
Nick Holt Avatar answered Oct 19 '22 16:10

Nick Holt