As far as I understand the source compatibility and how you can easily show an example that would break source compatibility (change name of the method, remove method etc.), I am having a bit of a problem seeing how binary compatibility can be broken in practice. Does anyone have a simple example of preservation of source compatibility that would cause binary compatibility issues i.e. no code changes are required but recompilation is necesssary?
4 Answers
One example (and this is by no means the only one) would be if the signature of a method in a library changes, in a compatible way. For example, consider:
// Library.java v1 public class Library { public static void print(String foo) { System.out.println(foo); } } // Client.java v1 public class Client { public static void main(String[] args) { Library.print("hello"); } } Compile and run:
$ javac Client.java Library.java $ java Client hello Now change Library.java - note the type of the foo parameter:
// Library.java v2 public class Library { public static void print(Object foo) { System.out.println(foo); } } Just recompile Library.java and try to rerun Client:
$ javac Library.java $ java Client Exception in thread "main" java.lang.NoSuchMethodError: Library.print(Ljava/lang/String;)V at Client.main(Client.java:3) Comments
First need to understand both compatibility.
Source compatibility - Program is source compatible with new version if Program can be compiled with that new version of code(library or api)
Binary compatibility - Program is binary compatible with new version of code if Program can be linked with that code without recompilation
Following link has more example for "Source compatible but Binary incompatible "
- Specialising Return Types

- Generalising Parameter Types

- Primitive vs Wrapper Types

Read http://praitheesh.blogspot.com.au/2014/09/compatibility-and-api-evolution-in-java.html for more details.
Comments
If you import an interface with string constants. (An anti-pattern in Java.)
Then the importing class copies the constants in the constant table, and uses those constants immediately. The import dependency to the interface then is missing.
When the string value of the constant in the interface is changed, the compiler does not see that it needs to recompile the class that will remain using the old value - as there is no longer an import to the interface.
The running is not broken, but the behaviour is - wrong value.
Comments
An example I met :
public class Class1 { public void do() { System.out.println("do!"); } } Client part :
public class Class2 { public void callDo() { Class1 c = new Class1(); c.do(); } } Now you change the return of do method :
public class Class1 { public String do() { System.out.println("do!"); return "done!"; } } If you run the client code without a recompilation you will get a NoSuchMethodError exception because the method signature has changed.