Diferencia entre los métodos estáticos y predeterminados en la interfaz


107

Estaba aprendiendo a través de interfaces cuando noté que ahora puede definir métodos estáticos y predeterminados en una interfaz.

public interface interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

    public default void menthod3() {
        System.out.println("default print");
    }
}

Por favor, explique la diferencia de los dos y también si hay un ejemplo de cuándo usaríamos esto sería bueno. Un poco confundido sobre interfaces.


4
¿Intentaste leer sobre métodos estáticos en el tutorial de Java?
Dawood ibn Kareem

1
¿Entonces te perdiste la parte de no poder anular un método estático?
Dawood ibn Kareem

1
no entendí lo mismo en las interfaces
Vipin Menon

9
El método estático es un miembro estático de la interfaz, no se puede anular (como con la clase), el método predeterminado es el default implementationde un método que podría anularse.
Shail016

2
Me pregunto: ¿por qué nunca aceptó una respuesta aquí?
GhostCat

Respuestas:


116

Diferencias entre los métodos estáticos y predeterminados en Java 8:

1) Los métodos predeterminados se pueden anular al implementar la clase, mientras que los estáticos no .

2) El método estático pertenece solo a la clase de interfaz, por lo que solo puede invocar el método estático en la clase de interfaz, no en la clase que implementa esta interfaz, consulte:

public interface MyInterface {
    default void defaultMethod(){
        System.out.println("Default");
    }

    static void staticMethod(){
        System.out.println("Static");
    }    
}

public class MyClass implements MyInterface {

    public static void main(String[] args) {

        MyClass.staticMethod(); //not valid - static method may be invoked on containing interface class only
        MyInterface.staticMethod(); //valid
    }
}

3) Tanto la clase como la interfaz pueden tener métodos estáticos con los mismos nombres, ¡y ninguno anula al otro!

public class MyClass implements MyInterface {

    public static void main(String[] args) {

        //both are valid and have different behaviour
        MyClass.staticMethod();
        MyInterface.staticMethod();
    }

    static void staticMethod(){
        System.out.println("another static..");
    }
}

2
pero ¿por qué 'estático'? ¿Para qué sirve en Java 8?
Shashank Vivek

4
El propósito de la palabra clave estática no cambia: definir miembros de nivel de clase: campos, métodos, etc. En Java 8, este comportamiento se expandió a Interfaces, por lo que se vuelven más similares a las clases y ahora pueden reemplazar la clase en la mayoría de los escenarios.
stinger

sí, pero todavía podemos ocultar el método estático de la interfaz en lugar de anularlo, .... creo que ambos cumplen lo mismo purpose( usan una implementación común ) y resuelven la ambigüedad implementing the logic again in subclass ( anulando, ocultando ). la única razón sensata sería la razón por la que [los métodos de interfaz estática no se heredan] ( stackoverflow.com/questions/25169175/… ) y por lo tanto no podemos llamarlos usando una instancia de subclase.
amarnath harish

29

Un método estático es un método que se aplica a la clase 'espacio de nombres', por así decirlo. Por tanto , se accede a un staticmétodo foode interfaz . Tenga en cuenta que la llamada a la función no se aplica a ninguna instancia en particularInterfaceInterface.foo() de la interfaz.

Por barotro lado, una implementación predeterminada es llamada por

Interface x = new ConcreteClass();
x.bar();

Un staticmétodo de interfaz no puede conocer la thisvariable, pero una implementación predeterminada sí.


19

1. explica la diferencia de los dos

Los métodos de interfaz estática son como métodos de clase estática (aquí pertenecen solo a la interfaz). Donde, como los métodos de interfaz predeterminados proporcionan métodos default implementationde interfaz (qué clases de implementación pueden override)
Pero recuerde que en caso de que una clase sea una implementing more than one interface with same defaultfirma de método, entonces la clase de implementaciónneeds to override the default method

Puede encontrar un ejemplo simple a continuación (puede hacer bricolaje para diferentes casos)

public class Test {
    public static void main(String[] args) {
        // Accessing the static member
        I1.hello();

        // Anonymous class Not overriding the default method
        I1 t = new I1() {
            @Override
            public void test() {
                System.out.println("Anonymous test");
            }
        };
        t.test();
        t.hello("uvw");

        // Referring to class instance with overridden default method
        I1 t1 = new Test2();
        t1.test();
        t1.hello("xyz");

    }
}

interface I1 {

    void test();
    //static method
    static void hello() {
        System.out.println("hello from Interface I1");
    }

    // default need not to be implemented by implementing class
    default void hello(String name) {
        System.out.println("Hello " + name);
    }
}

class Test2 implements I1 {
    @Override
    public void test() {
        System.out.println("testing 1234...");
    }

    @Override
    public void hello(String name) {
        System.out.println("bonjour" + name);
    }
}

2. cuándo usaríamos esto sería bueno.

Eso depende del planteamiento de su problema. Yo diría que los métodos predeterminados son útiles, si necesita la misma implementación para un método en su especificación en todas las clases de ese contrato, o puede usarse como Adapterclases.

aquí hay una buena lectura: /software/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

también a continuación, el documento de Oracle explica los métodos predeterminados y estáticos para desarrollar interfaces existentes:

Los usuarios que tienen clases que implementan interfaces mejoradas con nuevos métodos predeterminados o estáticos no tienen que modificarlos o recompilarlos para adaptarse a los métodos adicionales.

http://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html


Tengo una duda. ¿Es posible crear un objeto de una interfaz? Su código tiene esta línea: I1 t = new I1 ()
Hackinet

@Hackinet lea amablemente el comentario de Java sobre esa declaración. Lea también sobre las clases anónimas. Espero que te ayude.
Shail016

12

Aquí está mi punto de vista:

método estático en la interfaz:

  • Puede llamarlo directamente (InterfacetA.staticMethod ())

  • La subclase no podrá anularse.

  • La subclase puede tener un método con el mismo nombre que staticMethod

método predeterminado en la interfaz:

  • No puedes llamarlo directamente.

  • La subclase podrá anularlo

Ventaja:

  • Método estático: no es necesario crear una clase separada para el método de utilidad.

  • Método predeterminado: proporciona la funcionalidad común en el método predeterminado.


8

Este enlace tiene algunas ideas útiles, he enumerado algunas de ellas aquí.

Los métodos predeterminados y estáticos han reducido las diferencias entre las interfaces y las clases abstractas .

Métodos predeterminados de la interfaz :

  • Ayuda a evitar las clases de utilidad, como todo el método de la clase Colecciones se puede proporcionar en las propias interfaces.
  • Ayuda a extender las interfaces sin tener el temor de romper las clases de implementación.

Métodos estáticos de interfaz :

  • Son parte de la interfaz, no podemos usarla para implementar objetos de clase.
  • Ayuda a proporcionar seguridad al no permitir que las clases de implementación las anulen.

Me gustaría citar otra referencia útil .


3

Métodos predeterminados de la interfaz:

Ayuda a evitar las clases de utilidad, como todo el método de la clase Colecciones se puede proporcionar en las propias interfaces.

Ayuda a extender las interfaces sin tener el temor de romper las clases de implementación.

Métodos estáticos de interfaz:

Son parte de la interfaz, no podemos usarla para implementar objetos de clase.

Ayuda a proporcionar seguridad al no permitir que las clases de implementación las anulen.

Ahora como método estático que proporciona seguridad. Veamos un ejemplo.

interface MyInterface {
    /*
     * This is a default method so we need not to implement this method in the implementation classes
     */
    default void newMethod() {
        System.out.println("Newly added default method in Interface");
    }

    /*
     * This is a static method. Static method in interface is similar to default method except that we cannot override them in the implementation classes. Similar to default methods, we need to implement these methods in implementation classes so we can safely add them to the existing interfaces.
     */
    static void anotherNewMethod() {
        System.out.println("Newly added static method in Interface");
    }

    /*
     * Already existing public and abstract method We must need to implement this method in implementation classes.
     */
    void existingMethod(String str);
}

public class Example implements MyInterface {
    // implementing abstract method
    public void existingMethod(String str) {
        System.out.println("String is: " + str);
    }

    public void newMethod() {
        System.out.println("Newly added default method in Class");
    }

    static void anotherNewMethod() {
        System.out.println("Newly added static method in Class");
    }

    public static void main(String[] args) {
        Example obj = new Example();

        // calling the default method of class
        obj.newMethod();
        // calling the static method of class

        obj.anotherNewMethod();

        // calling the static method of interface
        MyInterface.anotherNewMethod();

        // calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn");

    }
}

Aquí obj.newMethod();, la lógica de implementación de la clase de impresión significa que podemos cambiar la lógica de ese método dentro de la clase de implementación.

Pero la obj.anotherNewMethod();lógica de implementación de la clase de impresión, pero no la implementación de la interfaz modificada. Entonces, si hay alguna lógica de cifrado-descifrado escrita dentro de ese método, no puede cambiarla.


esta respuesta parece que iba a algún lado bueno, y de repente ¡boom! ninguna explicación significativa al final. pero no cambió la implementación de la interfaz, ¿qué significa esto?
amarnath harish

2

Según Javadocs de Oracle: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Los métodos predeterminados le permiten agregar nuevas funciones a las interfaces de sus bibliotecas y garantizar la compatibilidad binaria con el código escrito para versiones anteriores de esas interfaces.

Un método estático es un método que está asociado con la clase en la que está definido en lugar de con cualquier objeto. Cada instancia de la clase comparte sus métodos estáticos.

Normalmente, el método estático en la interfaz se usa como métodos auxiliares, mientras que el método predeterminado se usa como una implementación predeterminada para las clases que implementan esa interfaz.

Ejemplo:

interface IDemo {

    //this method can be called directly from anywhere this interface is visible
    static int convertStrToInt(String numStr) {
       return Integer.parseInt(numStr);
    }


    //getNum will be implemented in a class
    int getNum();       

    default String numAsStr() {
       //this.getNum will call the class's implementation
       return Integer.toString(this.getNum());
    }   

}

1

Según el documento de Java14 JLS:

Método predeterminado:

  • Es un método de instancia declarado en una interfaz con el modificador predeterminado

  • Solo se puede acceder a él mediante la instancia de la clase de implementación.

  • Su cuerpo siempre está representado por un bloque, que proporciona una implementación o comportamiento predeterminado para cualquier clase de implementación sin anular el método.

  • Nunca puede ser estático o privado

Método estático:

  • Se puede invocar por interfaz sin hacer referencia a un objeto en particular, al igual que los métodos estáticos de clase

  • El método estático puede ser privado

  • La clase de implementación no puede acceder al método estático

Vamos a entenderlo con la ayuda del siguiente código de ejemplo:

            public interface MyInterface {
        
            private void privateMethod() {
                System.out.println("Hi, this is privateMethod");
            }
        
            private static void staticPrivateMethod() {
                System.out.println("Hi, this is staticPrivateMethod");
            }
        
            static void staticMethod() {
                //privateMethod();    // Non-static method cannot be referenced from a static contex
                System.out.println("Hi, this is staticMethod");
                staticPrivateMethod();
            }
        
            default void defaultMethod() {
                System.out.println("Hi, this is defaultMethod");
            }
        
        }
    
    public class MyInterfaceImpl implements MyInterface{
        public static void main(String[] args) {
    
            MyInterface.staticMethod();
            // myInterface.staticMethod(); // Not allowed
    
            MyInterface myInterface = new MyInterfaceImpl();
            myInterface.defaultMethod();
            // MyInterface.defaultMethod(); // Not allowed
    
        }
    }

0

no podemos ejecutar Interfacesample2.menthod3();porque no es un método estático. Para ejecutar method3()necesitamos una instancia de Interfacesample2interface.

Encuentre el siguiente ejemplo práctico:

public class Java8Tester {
   public static void main(String args[]){
      // Interfacesample2.menthod3(); Cannot make a static reference to the non-static method menthod3 from the type Interfacesample2

      new Interfacesample2(){ }.menthod3();// so in order to call default method we need an instance of interface

       Interfacesample2.method(); // it
   }
}

interface Interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

    public default void menthod3() {
        System.out.println("default print");
    }
}

0

El inicio de la interfaz de Java 8 también puede tener un método estático. Al igual que el método estático de una clase, el método estático de una interfaz se puede llamar mediante el nombre de la interfaz.

Ejemplo

public interface Calculator {
    int add(int a, int b);
    int subtract(int a, int b);

    default int multiply(int a, int b) {
         throw new RuntimeException("Operation not supported. Upgrade to UltimateCalculator");
    }

    static void display(String value) {
        System.out.println(value);
    }
}

La diferencia entre el método de interfaz estático y el predeterminado es que el método predeterminado admite la herencia, pero el método estático no. El método predeterminado se puede anular en la interfaz heredada.

Aquí hay una buena lectura sobre el método predeterminado de la interfaz y el método estático. Método predeterminado de interfaz en Java 8


0

Todas las buenas respuestas aquí. Me gustaría agregar otro uso práctico de la función estática en la interfaz. La sugerencia proviene del libro - Effective Java, 3rd Edition de Joshua Bloch en el Capítulo 2: Creación y destrucción de objetos.

Static functions can be used for static factory methods. 

Los métodos de fábrica estáticos son métodos que devuelven un objeto. Trabajan como constructor. En casos específicos, el método de fábrica estática proporciona un código más legible que el constructor.

Citando del libro - Effective Java, 3rd Edition por Joshua Bloch

Antes de Java 8, las interfaces no podían tener métodos estáticos. Por convención, los métodos de fábrica estáticos para una interfaz denominada Tipo se incluyeron en una clase complementaria no instantable (elemento 4) denominada Tipos.

El autor da un ejemplo de colecciones donde se implementa dicho método de fábrica estático. Verificando el código, Josh Bloch puede verse como el primer autor de la clase Colecciones. Aunque Collections es una clase y no una interfaz. Pero el concepto aún se aplica.

Por ejemplo, Java Collections Framework tiene cuarenta y cinco implementaciones de utilidades de sus interfaces, que proporcionan colecciones no modificables, colecciones sincronizadas y similares. Casi todas estas implementaciones se exportan a través de métodos de fábrica estáticos en una clase no instanciable (java.util.Collections). Las clases de los objetos devueltos no son públicas.

Además, explica que la API no solo es más pequeña, sino que ayuda con la legibilidad del código y la facilidad de la API.

No es solo la mayor parte de la API lo que se reduce, sino el peso conceptual: el número y la dificultad de los conceptos que los programadores deben dominar para utilizar la API. El programador sabe que el objeto devuelto tiene precisamente la API especificada por su interfaz, por lo que no es necesario leer documentación de clase adicional para la clase de implementación.

Aquí está uno de los métodos estáticos de la clase java.util.Collections:

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
    return new UnmodifiableCollection<>(c);
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.