Review First Java9 Migration Attempt
Yesterday i had looked what happens if i build AssertJ with the current Java9 (1.9.0-ea-b66) release and stumbled upon some things which i had not expected. To be true here i had expected that everything works fine. Mainly because AssertJ has almost no dependencies and does not use some fancy stuff like Unsafe. Maybe i was too optimistic. ;)
Problem 1: Compiler error with bounded generics with arrays/varargs
The first problem involves a specific combination of
- arrays/varargs
- bounded generics
- inferred types
and appears as a compiler error. Consider the following example which works fine with the latest Java8 (1.8.0_45-b14).
1 public class Example {
2 @SafeVarargs
3 public static <T> A<T> create(A<? extends T>... a) {
4 return allOf(a); //Compile error
5 }
6
7 @SafeVarargs
8 public static <T> A<T> allOf(A<? extends T>... a) {
9 return null;
10 }
11
12 class A<T> {}
13 }
1 de/bischinger/jdk9test/Example.java:11: error: method allOf in class
2 Example cannot be applied to given types;
3 return allOf(a);
4 ^
5 required: Example.A<? extends T#1>[]
6 found: Example.A<? extends T#2>[]
7 reason: cannot infer type-variable(s) T#1
8 (varargs mismatch; Example.A<? extends T#2>[] cannot be converted
9 to Example.A<? extends T#1>)
10 where T#1,T#2 are type-variables:
11 T#1 extends Object declared in method <T#1>allOf(Example.A<? extends T#1>...)
12 T#2 extends Object declared in method <T#2>create(Example.A<? extends T#2>...)
13 1 error
As the error message points out (with -Xdiags:verbose) Java9 is more strict when it comes to such constellations. I am not sure why this change was really necessary but it probably came with JEP-213.
Solution or Workaround?
The only workaround to that problem i was able to found looks as follows
1 public static <T> A<T> create(A<? extends T>... a) {
2 return Example.<T>allOf(a);
3 }
and looks ugly. The thing which makes it more ugly is that this cannot be done with an automatic refactoring via an IDE. ;(
Problem 2: XML PrettyPrint
The other thing i had found is that the behavior of XML pretty print does not work anymore. At first this does not sound like a problem but if your software is using this functionality and makes use of equals (which testing frameworks or tests sometimes do) then you probably have a problem.
At the moment i have not found a solution/workaround for it. So if you have any information about that please let me know.
1 public class PrettyPrint {
2 public static void main(String[] args) throws Exception {
3 String xml = "<rss version=\"2.0\"><channel> <title>Java Tutorials and Examples 1</title> <language>en-us</language></channel></rss>";
4 Writer stringWriter = createPrettyPrint(xml);
5 System.out.println(stringWriter.toString());
6 }
7
8 private static Writer createPrettyPrint(String xml) throws Exception {
9 DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
10 DOMImplementationLS domImplementation = (DOMImplementationLS) registry.getDOMImplementation("LS");
11 Writer stringWriter = new StringWriter();
12 LSOutput formattedOutput = domImplementation.createLSOutput();
13 formattedOutput.setCharacterStream(stringWriter);
14 LSSerializer domSerializer = domImplementation.createLSSerializer();
15 domSerializer.getDomConfig().setParameter("format-pretty-print", true);
16 // Set this to true if the declaration is needed to be in the output.
17 domSerializer.getDomConfig().setParameter("xml-declaration", true);
18 domSerializer.write(toXmlDocument(xml), formattedOutput);
19 return stringWriter;
20 }
21
22 private static Document toXmlDocument(String xmlString) throws Exception {
23 InputSource xmlInputSource = new InputSource(new StringReader(xmlString));
24 DocumentBuilder xmlDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
25 return xmlDocumentBuilder.parse(xmlInputSource);
26 }
27 }
Java9
1 <?xml version="1.0" encoding="UTF-8"?><rss version="2.0">
2 <channel> <title>Java Tutorials and Examples 1</title> <language>en-us</language>
3 </channel>
4 </rss>
Java8
1 <?xml version="1.0" encoding="UTF-8"?>
2 <rss version="2.0">
3 <channel>
4 <title>Java Tutorials and Examples 1</title>
5 <language>en-us</language>
6 </channel>
7 </rss>