java - Does introducing a default method to an interface really preserve back-compatibility? -
i think i'm confused introduction of default methods interfaces in java. understand it, idea default methods can introduced existing interfaces without breaking existing code.
if implement interface non-abstract class, (of course) have define implementations of abstract methods in interface. if interface defines default method, inherit implementation of method.
if implement 2 interfaces, have implement union of abstract methods defined in both interfaces. inherit implementation of default methods; if there happens collision between default methods in 2 interfaces, must override method in implementing class.
this sounds fine, following scenario?
suppose there's interface:
package com.example ; /** * version 1.0 */ public interface { public void foo() ; /** * answer life, universe, , everything. */ public default int getanswer() { return 42 ;} }
and second interface
package com.acme ; /** * version 1.0 */ public interface b { public void bar() ; }
so can write following:
package com.mycompany ; public class c implements com.example.a, com.acme.b { @override public void foo() { system.out.println("foo"); } @override public void bar() { system.out.println("bar"); } public static void main(string[] args) { system.out.println(new c().getanswer()); } }
so should fine, , indeed
java com.mycompany.c
displays result 42.
but suppose acme.com makes following change b:
package com.acme ; /** * version 1.1 */ public interface b { public void bar() ; /** * answer life, universe, , * @since 1.1 */ public default int getanswer() { return 6*9; } }
as understand it, introducing method supposed safe. if run existing com.mycompany.c against new version, runtime error:
exception in thread "main" java.lang.incompatibleclasschangeerror: conflicting default methods: com/example/a.getanswer com/acme/b.getanswer @ com.mycompany.c.getanswer(c.java) @ com.mycompany.c.main(c.java:12)
that's not entirely surprising, doesn't mean introducing default methods existing interfaces runs risk of breaking existing code? missing?
although adding default method same name in 2 interfaces make code fail compile, once resolve compilation error, binaries obtained after compiling both interfaces, , the class implementing interfaces, backward compatible.
so, compatibility binary compatibility. being explained in jls §13.5.6 - interface method declarations:
adding default method, or changing method abstract default, not break compatibility pre-existing binaries, may cause
incompatibleclasschangeerror
if pre-existing binary attempts invoke method. error occurs if qualifying type, t, subtype of 2 interfaces, , j, both , j declare default method same signature , result, , neither nor j subinterface of other.in other words, adding default method binary-compatible change because not introduce errors @ link time, if introduces errors @ compile time or invocation time. in practice, risk of accidental clashes occurring introducing default method similar associated adding new method non-final class. in event of clash, adding method class unlikely trigger linkageerror, accidental override of method in child can lead unpredictable method behavior. both changes can cause errors @ compile time.
the reason got incompatibleclasschangeerror
because, didn't recompile c
class, after adding default method in b
interface.
also see:
Comments
Post a Comment