Wednesday, April 30, 2014

Java 8 Overview: Default and Static Interface Methods

Introduction

With the release of Java 8 I thought a series of posts on the new features of Java 8 would be appropriate. Probably the simplest of the new concepts is the idea of default and static methods for interfaces. Basically, what you can now do is define a default set of functionality you want for a given interface. Before, you'd have to define an interface and then immediately define an abstract class that implements the interface where you could put the default implementation (Swing event adapter classes anyone?) To use default methods you simply need to put the keyword default before the method signature and implement the method.
Another inclusion with Java 8 are static methods in interfaces. Like default methods, you can declare any number of static methods inside the interface as well.

Example

Source

public class Main {
    public interface ContainsDefault {
        String greeting1();
        default String greeting2() {
            return "My Second Greeting";
        }
        static String greeting3() {
            return "My Third Greeting";
        }
    }

    public static class Override implements ContainsDefault {
        public String greeting1() {
            return "Alternate Override1";
        }

        public String greeting2() {
            return "Alternate Override2";
        }
    }

    public static class NoOverride implements ContainsDefault {
        public String greeting1() {
            return "My First Greeting";
        }
    }

    public static void main(String[] args) {
        ContainsDefault noOverride = new NoOverride();
        ContainsDefault override = new Override();
        System.out.println("noOverride,greeting1: " + noOverride.greeting1());
        System.out.println("noOverride,greeting2: " + noOverride.greeting2());
        System.out.println("override,greeting1: " + override.greeting1());
        System.out.println("override,greeting2: " + override.greeting2());
        System.out.println("containsDefault,greeting3: " + ContainsDefault.greeting3());
    }
}

Results

noOverride,greeting1: My First Greeting
noOverride,greeting2: My Second Greeting
override,greeting1: Alternate Override1
override,greeting2: Alternate Override2
containsDefault,greeting3: My Third Greeting

Advantages

This has a few advantages:
  • Less classes (you only need the interface, not that plus another abstract class with the default implementations, such as swing event adapter classes)
  • Moving the default implementations to the interface allows classes that use it that need the default implementation to still extend from another class.
  • You can now add new methods to existing interfaces and if you add a default method you won't need to go to each implementation to implement the method, where appropriate

Concerns

There are a few things you need to look out for when using default and static methods:
  • since there is a default implementation, implementing classes aren't required to implement the method at all so you should be careful with putting in defaults for methods that are central to the operation of your system
  • You still cannot define variables, even if they're public (static and final variables are still OK; but since they're public the outside world can already access them anyway) so the usefulness of the methods are limited

Conclusion

While default methods can provide an easier path for setting up interfaces to make them more useful programmers need to be careful not to apply them indiscriminately. They can render default adapters, like the swing event adapters, irrelevant and free up classes to extend others instead of the adapter class; but they can also hide issues when used for core methods that don't really have a default. At the end of the day they're just another arrow in a programmer's quiver that, if used with skill, will make their programs more concise and understandable.  

No comments:

Post a Comment