In recent Java versions, notably from Java 8 onwards, abstract classes have gained new capabilities and flexibility through the introduction of default methods and static methods. This has allowed developers to provide more reusable and versatile code while still maintaining the abstract nature of their classes.
Before Java 8, abstract classes could only contain abstract methods and concrete methods. However, with the advent of default methods, developers can now define methods with implementation within interfaces, allowing for a form of "multiple inheritance" of behavior. Abstract classes can still be used, but they can now leverage interfaces more effectively, leading to cleaner and more maintainable code.
abstract class Animal {
abstract void sound();
void sleep() {
System.out.println("Sleeping...");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound(); // Output: Bark
dog.sleep(); // Output: Sleeping...
}
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?