简体   繁体   中英

Are there any differences between a normal interface class and an abstract class that only has abstract methods?

I was just curious if they are treated any differently.

For example if we have:

The interface:

public interface Test {
    public void method();
}

And the abstract class:

public abstract class Test {
    public abstract void method();
}

Will the JVM treat these classes any differently? Which of the two takes up more disk space during storage , which one will use up the most runtime memory which one does more operations( performs better ).

This question isn't about when to use interfaces or abstract classes.

Yes, they are different.

With an interface, clients could implement it aswell as extend a class:

class ClientType implements YourInterface, SomeOtherInterface { //can still extend other types

}

With a class, clients will be able to extend it, but not extend any other type:

class ClientType extends YourClass { //can no longer extend other types

}

Another difference arises when the interface or abstract class have only a single abstract method declaration, and it has to do with anonymous functions (lambdas).

As @AlexanderPetrov said, an interface with one method can be used as a functional interface , allowing us to create functions "on-the-fly" where ever a functional interface type is specified:

//the interface
interface Runnable {
    void run()
}

//where it's specified
void execute(Runnable runnable) {
    runnable.run();
}

//specifying argument using lambda
execute(() -> /* code here */);

This cannot be done with an abstract class . So you cannot use them interchangably. The difference comes in the limitations of how a client can use it, which is enforced by the semantics of the JVM.

As for differences in resource usage, it's not something to worry about unless it's causing your software problems . The idea of using a memory-managed language is to not worry about such things unless you are having problems. Don't preoptimize, I'm sure the difference is negligable. And even if there is a difference, it should only matter if it may cause a problem for your software.

If your software is having resource problems, profile your application. If it does cause memory issues, you will be able to see it, as well as how much resources each one consumes. Until then, you shouldn't worry about it. You should prefer the feature that makes your code easier to manage, as opposed to which consumes the least amount of resources.

JVM internals and memory representation It will be almost the same for the JVM. My statement is based on Chapter 4 - Class file Format . As seen from the attached documentation the JVM is making difference between a class and interface, by the access_flags . If you have a Simple interface with just one method and a simple abstract class with just one method . Most of the fields in this format will be the same (empty) and the main difference will be the access_flags.

Default constructor generation abstract class As @Holger pointed out, another small difference between the Interface and Abstract class is that ordinary classes require a constructor. The Java compiler will generate a default constructor for the Abstract class which will be invoked for each of its subclasses. In that sense the abstract class definition will be slightly bigger compared to the interface.

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];
}

Besides the multiple inheritance of interfaces, another difference is that in Java8 abstract class with only one method is not a Functional interface .

 @FunctionalInterface
 public interface SimpleFuncInterface {
      public void doWork();
 }

 execute(SimpleFuncInterface function) {
      function.doWork();
 }

 execute(()->System.out.printline("Did work"));

Same can not be achieved with abstract class.

Interfaces - lack of "Openness to extension". Up to Java 8 Interfaces have been criticized for their lack of extensibility. If you change the interface contract you need to refactor all clients of an interface.

One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.

With the introduction of Java 8 Interface Default method this lack of extensibility has been addressed.

public interface MyInterface {
 int method1();
 // default method, providing default implementation
 default String displayGreeting(){
  return "Hello from MyInterface";
 }
}

With Java 8 new methods can be added both to interfaces and abstract classes without breaking the contract will the client classes. http://netjs.blogspot.bg/2015/05/interface-default-methods-in-java-8.html

They are different in implementation

  • you can only extend only one abstract class
  • On the other hand you can implement multiple interfaces at the same time
  • You need to implement all method present in an interface
  • for abstract it may provide some default implementation so you are independent whether you want to implement it again or just used the default implementation

If you talking about performance, then sometime ago there was an opinion that interfaces are slower than abstract classes. But now JIT makes no difference between them.

Please, see this answer for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM