What is the purpose of the default when used in the signature of a method?

5

Within the List<E> interface of Java there is the replaceAll() method whose purpose is to replace all occurrences of a specified value in a list.

However, in your signature it uses the command default , this has confused me, it is the first time I see the default being used when signing a method, see your complete signature:

default void replaceAll(UnaryOperator<E> operator)

What is the purpose of default when it is used in signing a method as in the example above?

    
asked by anonymous 08.03.2016 / 22:04

2 answers

6

The purpose of a default method is to provide a default implementation for an interface method in case the classes implementing the interface do not implement the method.

Remember that a Java interface is like a contract. The classes (except the abstract ones) that implement the interface must implement all interface methods as a contract obligation, otherwise they do not compile.

In theory, there is no reason to implement a method in an interface, but there are some practical reasons, among which are:

Add features without breaking existing code

This is the case of the example quoted in the question, from the List interface.

Before default methods, if you wanted to add a common method to an interface you would potentially break the agreement and all classes implementing it would need to be modified.

In the case of List , consider that it is one of the most used APIs, and several libraries and systems have their own implementations. This would be an impediment to migrating to the new version of Java until all dependencies and components were updated.

The main goal of default methods is to enable APIs to evolve seamlessly, without fuss, since "old" code can use a newer API without having to be updated.

This is especially advantageous when the new method adds some functionality, but is not strictly necessary for "old" mode operation.

Of course, this does not solve the problem when a change in the operation of an API occurs, because in this case the existing methods would need to be modified and default methods are not recommended.

In a simple example, imagine an interface of a DAO like this:

public interface ClienteDao {
    void incluir(Cliente c);
}

Now imagine that this DAO has multiple implementations across multiple modules of a large system. Different teams are responsible for the different modules which in turn are put into production at different times.

In version 2.0 of the system, you add a new method in the interface, but you can not expect all other modules to be updated. You could do this:

public interface ClienteDao {
    void incluir(Cliente c);
    default void incluir(List<Cliente> clientes) {
        for (Cliente c : clientes) incluir(c);
    }
}

Okay, now the system API is up to date and everything keeps running.

While other teams do not implement the new method, the default version serves the purposes well. Probably not the most optimized thing in the world, but it works.

For an in-memory DAO, the default implementation is probably sufficient. When a team that implements DAO for a particular database is to upgrade its module, they can implement an optimized version to include batch clients.

Flexibility in code reuse

Reusing code via inheritance is not usually a good practice, but the reality is that having methods in interfaces enables a special type of multiple inheritance or even be considered a type of trait .

In Java 6 you could reuse methods from other classes using import static to access static methods as if they were part of the class. But with the default methods of Java 8 you can implement an interface to bring a set of methods to your class.

The advantage of this over import static is that the methods are part of the class API and can be used polymorphically.

The advantage over delegating to other classes is that the code gets cleaner.

The advantage over inheritance is that you can "inherit" methods from multiple interfaces.

Incidentally, the entire Java API would be different if default methods existed longer.

A simple example could be a more flexible generic DAO, usually implemented using an abstract class. If you have any experience with systems you know there are always exceptions and not all DAOs need to have all methods. This occurs, for example, in entities that are read-only.

Example:

public interface GenericDao<T> {
    default Connection getConnection() {
        return DbUtils.getConnection();
    }
}

public interface ReadOnlyDao<T> extends GenericDao<T> {
    T instanciar(ResultSet rs); //específico para cada entidade
    default T recuperar(int id) {
        Connetion c = getConnetion();
        ... executa SQL usando alguma mágica ...
        return instanciar(rs);
    }
    default List<T> listarTodos() {
        ...
    }
}

public interface WriteOnlyDao<T> extends GenericDao<T> {
    void set(PreparedStatement st, T entidade); //coloca os parâmetros da entidade na query
    default void incluir(T entidade) {
        Connetion c = getConnetion();
        ... executa SQL usando alguma mágica ...        
    }
}

public interface DaoCompleto extends ReadOnlyDao, WriteOnlyDao {}

With these implementations, just implement the interfaces as needed:

public class FeriadosDao implements ReadOnlyDao { ... }
public class LogAcessoDao implements WriteOnlyDao { ... }
public class ClienteDao implements DaoCompleto { ... }

And right away, we can incorporate features in granular form as needed.

    
09.03.2016 / 07:00
6

Java 8 allows having so-called default methods . These are methods whose implementation may already be available in the interface (which could not happen before). Thus all classes that implement this interface already gain an implementation of the method. Of course the class can override this implementation if you want.

The keyword is being used only to tell the compiler that you know what you are doing, that you are implementing an algorithm on the interface with awareness that this is what you really want, it was not an accident.

08.03.2016 / 22:10