On Fri, 10 Jun 2022 at 14:10, Sumanth Rajkumar <rajkumar.suma...@gmail.com> wrote:
> For 1) I ran mvn verify and found the following errors > > > org.apache.commons.numbers.complex.Complex.getImaginary():METHOD_NOW_ABSTRACT, > org.apache.commons.numbers.complex.Complex.getReal():METHOD_NOW_ABSTRACT, > org.apache.commons.numbers.complex.Complex:CLASS_NOW_ABSTRACT, > org.apache.commons.numbers.complex.Complex:CLASS_TYPE_CHANGED, > > org.apache.commons.numbers.complex.ComplexCartesianImpl:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE, > > org.apache.commons.numbers.complex.ComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE, > > org.apache.commons.numbers.complex.ImmutableComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE > > These are expected changes... Is there a compatibility issue here? > Yes. These are reported as errors. One point here is that Complex is a final class. So some of the errors regarding inheritance are non-issues. However binary compatibility requires that a class compiled against the old version can run against the new one. The main issue is changing a class to an interface (type change). The japicmp plugin does not have a lot of documentation. You can try revapi instead. Put this in the plugins section of the pom.xml: <plugin> <groupId>org.revapi</groupId> <artifactId>revapi-maven-plugin</artifactId> <version>0.14.6</version> <dependencies> <dependency> <groupId>org.revapi</groupId> <artifactId>revapi-java</artifactId> <version>0.26.1</version> </dependency> </dependencies> </plugin> Then run: mvn revapi:check (if you have the jar package) mvn package revapi:check -DskipTests -Djavadoc.skip (if you don't) This will output some similar compatibility errors and link to online documentation that explains why it is a problem. This is the main issue: https://revapi.org/revapi-java/differences.html#java.class.kindChanged Changing a class to an interface. In this case methods on the object are invoked using a different instruction. Save this as Test.java: public class Test { static class A { public int getAnswer() { return 42; } } interface B { int getAnswer(); } static class Bimp implements B { public int getAnswer() { return 13; } } public static void main(String[] args) { A a = new A(); System.out.println(a.getAnswer()); B b = new Bimp(); System.out.println(b.getAnswer()); } } > javac Test.java > java Test 42 13 > javap -c Test ... 12: invokevirtual #16 // Method Test$A.getAnswer:()I ... 30: invokeinterface #29, 1 // InterfaceMethod Test$B.getAnswer:()I ... Here we see the interface method uses 'invokeinterface' and the class method uses 'invokevirtual'. So if you change class A to an interface then Test will have a runtime linkage error as it cannot find the method (this is all assuming that A, B and Bimp are in their own class files which I didn't do here for simplicity). Basically if a class thinks the object with a method is a class and it is changed on the classpath at runtime to an interface this will not work. Thus we have to keep Complex as a class. However it does not mean the methods cannot be moved to e.g. public final class ComplexFunctions { interface ComplexResult<R> { R accept(double real, double imag); } public static <R> R conj(double real, double imaginary, ComplexResult<R> result) { return result.accept(real, -imaginary); } } And Complex changed to e.g: ComplexFunctions conj() { return ComplexMath.conj(real(), imag(), Complex::ofCartesian); }