Source code compatibility between java 7 & 8 for o

2019-07-21 16:45发布

问题:

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.

回答1:

You can't use something compiled in Java 8 (for instance) in a lower version (say Java 7). You will get something like Unsupported major.minor version.... You need to use two JARs, one for version 1.7 and the other one for version 1.8. Eventually, the one for the 1.7 can't have that SQLType if it's not supported on that JDK; on the other hand, you are encouraged to maintain the overloaded version when you do the 1.8 version.

Notice that this doesn't have nothing to do with backwards compatibility.



回答2:

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 the ResultSet interface, there should be no problems as that interface doesn’t have that offending updateObject 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 return ResultSet instead of a more specific type. The same applies to the Connection returned by the Driver and the Statement returned by the Connection. It’s tempting to use covariant return types to declare your specific implementation classes but whenever your methods declare the interface type instead, you are guiding the application programmers to an interface 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).