简体   繁体   中英

Can I cross compile Java code that optionally uses classes from Java 8 but is compiled to Java 6?

I know that cross compiled Java code cannot use new language features, IE no features like lambdas from Java 8 or try-with-resources from Java 7.
But is it possible to refer to new classes that are added in new Java versions?

Say I have a library that supports Java 6+ and I have some method that accepts a date as an argument.
For Java 6 I offer an API using java.util.Date , but for users of Java 8 I wanted to offer the option of using java.time.Instant .

I would expect the Java 6 users to be able to use the library but encounter a ClassNotFoundException if they try using the Instant method.

Is there an accepted way of doing something like this, and how would it be achieved with common build tools like Gradle or Maven?

The example given is contrived, please don't give answers on alternative approaches to dealing with time.

It is not possible to do cleanly. APIs that mention Java 8 types cannot be loaded on a Java 6 JRE.

If your API uses Java 8 classes, then a Java 6 client cannot compile against it. In theory, you could replace the Java 8 classes with (say) java.lang.Object and require the client code to cast to either java.util.Date or java.time.Instant depending on the execution platform. But I don't see how that would be acceptable, let alone useful to programmers trying to use your libraries.

And you'd need to change your APIs anyway.


If you really need to support Java 6 and you also want to start using Java 8 features in your APIs, I would advise supporting two separate APIs:

  • one for Java 6 that uses only Java 6, and
  • another that uses Java 8 types as well.

You may be able to share some of the code behind the two versions of your APIs, but it depends on how "deep" the Java 8 dependencies go.

However, a better idea would be to bite the bullet and stop supporting Java 6 compatibility. Java 6 reached its end-of-life in February 2013. IMO, you are justified in putting a freeze on your Java 6 API, and then treating your Java 8 API as a new release that requires your client to switch to Java 8.

I think if you compile with javac (or Gradle or Maven) from Java 8 with target version Java 6 but without setting the classpaths from Java 6 it should work. But you might need to split on class level, not on method level.

Backporting

As the other Answers explain, basically the answer is “No”. A workaround is to use code that back-ports functionality to an earlier version of Java.

Regarding the java.time classes specifically:

  • ThreeTen-Backport
    Much of the java.time functionality is back-ported to Java 6 & 7 in the ThreeTen-Backport project.
  • ThreeTenABP
    The above back-port is further adapted to Android in the ThreeTenABP project.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM