I have created a single jar for Java 7 & 8 for a JDBC driver (using -source/-target compile options). However, I am having difficulty compiling applications that use the new/overloaded methods in the ResultSet
interface:
//New in Java 8
updateObject(int columnIndex, Object x, SQLType targetSqlType)
// Available in Java 7
updateObject(int columnIndex, Object x, int targetSqlType)
Note that SQLType is a new interface introduced in Java 8.
I have compiled the driver using Java 8, which worked fine. However, when any application using the driver accesses the method updateObject(int, Object, int)
from Java 7, it gets a compilation error saying “class file for java.sql.SQLType not found”, although the application is not using SQLType
. I think this is because Java looks at all the overloaded methods to determine the most specific one, and when doing so it can not access the new updateObject
method in Java 8 (as SQLType
is not defined in Java 7). Any idea how I can resolve this issue?
Note that the updateObject
method has a default implementation in the ResultSet
interface in Java 8 --- so I can not even use a more generic type instead of SQLType in the new method. In that case any application that uses the new method gets a compilation error saying updateObject
is ambiguous.
You can't use something compiled in
Java 8
(for instance) in a lower version (sayJava 7
). You will get something likeUnsupported major.minor version...
. You need to use two JARs, one for version1.7
and the other one for version1.8
. Eventually, the one for the1.7
can't have thatSQLType
if it's not supported on that JDK; on the other hand, you are encouraged to maintain the overloaded version when you do the1.8
version.Notice that this doesn't have nothing to do with backwards compatibility.
In this case, I would call it the application’s fault. After all, your class is implementing the
ResultSet
interface and applications using JDBC should be compiled against that interface instead of your implementation class.If a Java 7 application is compiled under Java 7 (where
SQLType
does not exist) against the Java 7 version of theResultSet
interface, there should be no problems as that interface doesn’t have that offendingupdateObject
method and it doesn’t matter which additional methods an implementation class has. If done correctly, the compiler shouldn’t even know that the implementation type will be your specific class.You may enforce correct usage by declaring the methods of your
Statement
implementation class to returnResultSet
instead of a more specific type. The same applies to theConnection
returned by theDriver
and theStatement
returned by theConnection
. It’s tempting to use covariant return types to declare your specific implementation classes but whenever your methods declare theinterface
type instead, you are guiding the application programmers to aninterface
based usage avoiding the problems described in your question.The application programmer still may use a type cast, or better
unwrap
, to access custom features of your implementation if required. But then it’s explicit and the programmer knows what potential problems may occur (and how to avoid them).