Si encuentras algún detalle que no entiendes puedes dejarlo en la sección de comentarios y trataremos de ayudarte lo mas rápido que podamos.
Solución:
Sí, son diferentes.
Con una interfaz, los clientes pueden implementarla y extender una clase:
class ClientType implements YourInterface, SomeOtherInterface //can still extend other types
Con una clase, los clientes podrán extenderla, pero no extenderán ningún otro tipo:
class ClientType extends YourClass //can no longer extend other types
Otra diferencia surge cuando el interface
o abstract class
tienen solo una declaración de método abstracto y tiene que ver con funciones anónimas (lambdas).
Como dijo @AlexanderPetrov, una interfaz con un método se puede utilizar como interfaz funcional, lo que nos permite crear funciones “sobre la marcha” siempre que se especifique un tipo de interfaz funcional:
//the interface
interface Runnable
void run()
//where it's specified
void execute(Runnable runnable)
runnable.run();
//specifying argument using lambda
execute(() -> /* code here */);
Esto no se puede hacer con un abstract class
. Por lo tanto, no puede usarlos de manera intercambiable. La diferencia radica en las limitaciones de cómo un cliente puede usarlo, que se aplica mediante la semántica de la JVM.
En cuanto a las diferencias en el uso de recursos, no es algo de lo que preocuparse a menos que esté causando problemas de software. La idea de utilizar un lenguaje administrado por la memoria es no preocuparse por esas cosas a menos que tenga problemas. No preoptimice, estoy seguro de que la diferencia es insignificante. E incluso si hay una diferencia, solo debería importar si puede causar un problema para su software.
Si su software tiene problemas de recursos, perfile su aplicación. Si causa problemas de memoria, podrá verlo, así como la cantidad de recursos que consume cada uno. Hasta entonces, no debes preocuparte por eso. Debería preferir la función que hace que su código sea más fácil de administrar, en lugar de la que consume la menor cantidad de recursos.
Componentes internos de JVM y representación de la memoria
Será casi lo mismo para la JVM. Mi declaración se basa en Capítulo 4 – Formato de archivo de clase. Como se ve en la documentación adjunta, JVM está marcando la diferencia entre una clase y una interfaz, por el access_flags. Si tiene una interfaz simple con solo un método y una clase abstracta simple con solo un método. La mayoría de los campos en este formato serán los mismos (vacíos) y la principal diferencia serán las banderas de acceso.
Clase abstracta de generación de constructor predeterminada
Como señaló @Holger, otra pequeña diferencia entre la interfaz y la clase abstracta es que las clases ordinarias requieren un constructor. El compilador de Java generará un constructor predeterminado para la clase Abstract que se invocará para cada una de sus subclases. En ese sentido, la definición de clase abstracta será un poco más grande en comparación con la interfaz.
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
ClassFile
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
Además de la herencia múltiple de interfaces, otra diferencia es que en La clase abstracta Java8 con un solo método no es una interfaz funcional.
@FunctionalInterface
public interface SimpleFuncInterface
public void doWork();
execute(SimpleFuncInterface function)
function.doWork();
execute(()->System.out.printline("Did work"));
No se puede lograr lo mismo con la clase abstracta.
Interfaces: falta de “apertura a la extensión”.
Las interfaces hasta Java 8 han sido criticadas por su falta de extensibilidad. Si cambia el contrato de interfaz, debe refactorizar todos los clientes de una interfaz.
Un ejemplo que me viene a la mente es Java MapReduce API para Hadoop, que se cambió en la versión 0.20.0 para favorecer las clases abstractas sobre las interfaces, ya que son más fáciles de evolucionar. Lo que significa que se puede agregar un nuevo método a la clase abstracta (con implementación predeterminada), sin romper las implementaciones antiguas de la clase.
Con la introducción de Método predeterminado de la interfaz de Java 8
se ha abordado esta falta de extensibilidad.
public interface MyInterface
int method1();
// default method, providing default implementation
default String displayGreeting()
return "Hello from MyInterface";
Con Java 8 se pueden agregar nuevos métodos tanto a interfaces como a clases abstractas sin romper el contrato con las clases del cliente. http://netjs.blogspot.bg/2015/05/interface-default-methods-in-java-8.html