# API Evolution

API tooling is about controlling API Evolution and Version Numbering.

Read Achieving API Binary Compatibility for understanding the various incompatibilities.

The following API incompatibilities have been explained in more detail below :

1. Field Addition to Class
2. Field Addition to Interface
3. Default Method Addition to Interface

## Field Addition to Class

Adding an API field to an API class that is extended by Clients is dangerous in two respects:

- It may break API contract compatibility similar to Evolving_Java-based_APIs#Example_4_-_Adding_an_API_method in case of name clashes.
- It may cause linkage errors in case an instance (respectively static) field hides a static (respectively instance) field, see JLS8 13.4.8.

  Example - Adding a Field to Class

      public class Base {String h = "Base";}
      public class Derived extends Base { }

      public class Test {
          public static void main(String[] args) {
               String s = new Derived().h;
               System.out.println(s);
          }
      }

  This program produces the output:

  Base

  Suppose that a public static field h is added to `Derived`:

        public class Derived extends Base { public static String h = "humongous"; }

  If `Derived` is recompiled but not `Test`, then running the new binary with the existing binary for `Test` will cause an `IncompatibleClassChangeError`.

  Furthermore, if char type h is added to Derived instead, there would be compilation error.

  This can not happen if all field declarations follow the usual naming conventions from JLS8 6.1 and classes only have API fields that are either
  - "static final" (and hence have a name that doesn't contain any lowercase letters), or
  - non-static and non-final (and hence have a name that contains a least one lowercase letter)

Apart from the binary compatibility issues, it is generally good software engineering practice that API classes should not expose any non-constant fields.

## Field Addition to Interface

Adding an API field to an API interface that is implemented by Clients is dangerous in two respects:

- It may break API contract compatibility similar to Evolving_Java-based_APIs#Example_4_-_Adding_an_API_method in case of name clashes.
- It may cause linkage errors in case an instance (respectively static) field hides a static (respectively instance) field, see JLS8 13.4.8. This can not happen if all field declarations follow the usual naming conventions from JLS8 6.1 and classes only have API fields that are either
  - "static final" (and hence have a name that doesn't contain any lowercase letters), or
  - non-static and non-final (and hence have a name that contains a least one lowercase letter)

## Default Method Addition to Interface

Adding a default method will break an existing client type if it already implements another interface that declares a default method with a matching signature, and the client type already refers to the default method from the other interface (except when using the Interface.super.method() notation). The added default method will cause an IncompatibleClassChangeError at run time, see JLS8 13.5.6. Furthermore, re-compiling the type will result in a compile error.

Example - Adding A Default Method

    API
     public interface interfaceAPI {}

    Client Code
     public interface clientInterface {
        default void doSomething() {
            System.out.println("Do something client...") ;
        }
    }

    public class ClientCode implements clientInterface, interfaceAPI {
        public static void main(String[] args) {
            new ClientCode().doSomething();
       }
    }

This program produces the output:

Do something client...

Suppose that a default method is added to `interfaceAPI`:

    public interface interfaceAPI {
        default void doSomething() {
            System.out.println("Do something API...");
        }
    }

If `interfaceAPI` is recompiled but not `ClientCode`, then running the new binary with the existing binary for `ClientCode` will cause an `IncompatibleClassChangeError`.