Interfaces de marcadores em Java

Interfaces de marcadores em Java

1. Introdução

Neste tutorial rápido, aprenderemos sobre interfaces de marcador em Java.

2. Interfaces de marcadores

Uma interface de marcador é uminterface quehas no methods or constants inside it. Ele fornecerun-time type information about objects, para que o compilador e a JVM tenhamadditional information about the object.

Uma interface de marcador também é chamada de interface de marcação.

Embora as interfaces de marcador ainda estejam em uso, elas provavelmente apontam para um cheiro de código e devem ser usadas com cuidado. A principal razão para isso é que eles confundem as linhas sobre o que uma interface representa, uma vez que os marcadores não definem nenhum comportamento. O desenvolvimento mais recente favorece as anotações para resolver alguns dos mesmos problemas.

3. Interfaces de marcadores JDK

Java tem muitas interfaces de marcador integradas, comoSerializable,Cloneable eRemote.

Vejamos o exemplo deCloneable interface. Se tentarmos clonar um objeto que não implementa esta interface, a JVM lança umCloneNotSupportedException. Portanto, oCloneablemarker interface is an indicator to the JVM que podemos chamar de métodoObject.clone().

Da mesma forma, ao chamar o métodoObjectOutputStream.writeObject(),the JVM checks if the object implements the Serializable marker interface. Quando não é o caso, umNotSerializableException é lançado. Portanto, o objeto não é serializado para o fluxo de saída.

4. Interface de Marcador Personalizado

Vamos criar nossa própria interface de marcador.

Por exemplo, podemos criar um marcador que indica se um objeto pode ser removido do banco de dados:

public interface Deletable {
}

Para excluir uma entidade do banco de dados, o objeto que representa essa entidade deve implementar nossa interfaceDeletable marker:

public class Entity implements Deletable {
    // implementation details
}

Digamos que temos um objeto DAO com um método para remover entidades do banco de dados. Podemos escrever nosso métododelete() para queonly objects implementing our marker interface possa ser excluído:

public class ShapeDao {

    // other dao methods

    public boolean delete(Object object) {
        if (!(object instanceof Deletable)) {
            return false;
        }

        // delete implementation details

        return true;
    }
}

Como podemos ver,we are giving an indication to the JVM, about the runtime behavior of our objects. Se o objeto implementa nossa interface de marcador, ele pode ser excluído do banco de dados.

5. Interfaces de Marcador vs. Anotações

Ao introduzir anotações, Java nos forneceu uma alternativa para obter os mesmos resultados que as interfaces de marcador. Além disso, como interfaces de marcador, podemos aplicar anotações a qualquer classe e usá-las como indicadores para executar determinadas ações.

Então, qual é a principal diferença?

Ao contrário das anotações, as interfaces nos permitem take advantage of polymorphism. Como resultado, podemos add additional restrictions to the marker interface.

Por exemplo, vamos adicionar uma restrição de que apenas um tipoShape pode ser removido do banco de dados:

public interface Shape {
    double getArea();
    double getCircumference();
}

Nesse caso, nossa interface de marcador, vamos chamá-la deDeletableShape,, terá a seguinte aparência:

public interface DeletableShape extends Shape {
}

Então nossa classe implementará a interface do marcador:

public class Rectangle implements DeletableShape {
    // implementation details
}

Portanto,all DeletableShape implementations are also Shape implementations. Obviamente,we can’t do that using annotations.

No entanto, cada decisão de design tem compensações epolymorphism can be used as a counter-argument contra interfaces de marcador. In our example, every class extending Rectangle will automatically implement DeletableShape.

6. Interfaces de Marcador vs. Interfaces típicas

No exemplo anterior, poderíamos obter os mesmos resultados modificando o métododelete() do nosso DAO para testar se nosso objeto éShape ou não, em vez de testar se éDeletable:

public class ShapeDao {

    // other dao methods

    public boolean delete(Object object) {
        if (!(object instanceof Shape)) {
            return false;
        }

        // delete implementation details

        return true;
    }
}

Então, por que criar uma interface de marcador quando podemos obter os mesmos resultados usando uma interface típica?

Vamos imaginar que, além do tipoShape, queremos remover o tipoPerson do banco de dados também. Nesse caso, existem duas opções para conseguir isso:

A primeira opção éto add an additional check to our previous delete() method para verificar se o objeto a ser excluído é uma instância dePerson ou não.

public boolean delete(Object object) {
    if (!(object instanceof Shape || object instanceof Person)) {
        return false;
    }

    // delete implementation details

    return true;
}

Mas e se tivermos mais tipos que também queremos remover do banco de dados? Obviamente, esta não será uma boa opção porque temosto change our method for every new type.

A segunda opção éto makethe Person type implement the Shape interface, que atua como uma interface de marcador. Mas um objetoPerson é realmente umShape? A resposta é claramente não, e isso piora a segunda opção que a primeira.

Portanto, emborawe can achieve the same results by using a typical interface as a marker, we’ll end up with a poor design.

7. Conclusão

Neste artigo, discutimos o que são interfaces de marcador e como elas podem ser usadas. Em seguida, analisamos alguns exemplos Java integrados desse tipo de interface e como eles são usados ​​pelo JDK.

Em seguida, criamos nossa própria interface de marcador e a pesamos no uso de uma anotação. Finalmente, acabamos vendo por que é uma boa prática usar uma interface de marcador em alguns cenários, em vez de uma interface tradicional.

Como sempre, o código pode ser encontrado emGitHub.