En Java, les interfaces servent de contrats auxquels les classes doivent adhérer. Puisqu'une interface ne fournit que la connaissance de ce qui peut être fait (via les signatures de méthodes) et cache comment cela se fait (en laissant l'implémentation aux classes qui implémenter l'interface), il réalise l'abstraction. Cette séparation du quoi du comment est l'idée centrale derrière l'abstraction.
Avec Java 8, les interfaces ont évolué au-delà du comportement purement abstrait, prenant en charge les méthodes par défaut et statique pour améliorer la flexibilité et la compatibilité ascendante.
Cet article plonge dans les interfaces, leurs fonctionnalités clés et les distinctions entre les interfaces et les classes abstraites, avec des exemples de code pour vous aider à comprendre les concepts.
Une interface en Java spécifie un ensemble de comportements (méthodes) que la classe d'implémentation doit suivre. Il ne contient que les signatures de méthode et les constantes. Contrairement aux classes abstraites, les interfaces permettent un héritage multiple en permettant à une classe d'implémenter plusieurs interfaces.
Les variables dans les interfaces sont implicitement publiques, statiques et finales.
Toutes les méthodes sont implicitement publiques et abstraites (avant Java 8).
Une classe peut implémenter plusieurs interfaces, surmontant ainsi la limitation d'héritage unique des classes.
À partir de Java 8, les interfaces peuvent également contenir des méthodes par défaut et statiques, améliorant ainsi la compatibilité ascendante.
package oops.interfaces; public interface InterfaceBasics { // Variables are public, static, and final by default // Initialization can only be done with declaration (No Static Blocks) // Compiler Interpretation: public static final int id = 90; int id = 90; // Abstract method (public and abstract by default) // Compiler Interpretation: public abstract void abstractMethod(); void abstractMethod(); // Default method - Introduced in Java 8 (public by default) // Compiler Interpretation: public default void concreteMethod() default void concreteMethod() { System.out.println("Concrete Method Called"); } // Static method - Introduced in Java 8 (public by default) // Compiler Interpretation: public static void staticMethod() static void staticMethod() { System.out.println("Static Method Called"); } }
1. Variables dans les interfaces :
Remarque : les variables finales statiques peuvent être initialisées soit au moment de la déclaration, soit dans des blocs statiques. Cependant, comme les interfaces n'autorisent pas les blocs statiques, ces variables doivent être initialisées lors de la déclaration.
2. Méthodes abstraites :
3. Méthodes par défaut :
4. Méthodes statiques :
package oops.interfaces; public interface InterfaceBasics { // Variables are public, static, and final by default // Initialization can only be done with declaration (No Static Blocks) // Compiler Interpretation: public static final int id = 90; int id = 90; // Abstract method (public and abstract by default) // Compiler Interpretation: public abstract void abstractMethod(); void abstractMethod(); // Default method - Introduced in Java 8 (public by default) // Compiler Interpretation: public default void concreteMethod() default void concreteMethod() { System.out.println("Concrete Method Called"); } // Static method - Introduced in Java 8 (public by default) // Compiler Interpretation: public static void staticMethod() static void staticMethod() { System.out.println("Static Method Called"); } }
Accès à la méthode :
La méthode par défaut (concreteMethod()) et la méthode remplacée (abstractMethod()) sont accessibles à l'aide de l'instance de classe obj, démontrant comment les deux types de méthodes peuvent être appelées.
Accès aux variables d'interface :
L'identifiant de la variable d'interface est accessible à la fois en utilisant le nom de l'interface (InterfaceBasics.id) et le nom de la classe d'implémentation (InterfaceBasicsImpl.id). Cela montre que les variables finales statiques d'une interface sont héritées, permettant à la classe d'implémentation de faire référence à la variable.
Accès à la méthode statique :
La méthode statique staticMethod() ne peut être appelée qu'en utilisant le nom de l'interface (InterfaceBasics.staticMethod()). Tenter d'y accéder via la classe d'implémentation (InterfaceBasicsImpl.staticMethod()) entraîne une erreur de compilation, car les méthodes statiques dans les interfaces ne sont pas héritées.
package oops.interfaces; public interface InterfaceBasics { // Variables are public, static, and final by default // Initialization can only be done with declaration (No Static Blocks) // Compiler Interpretation: public static final int id = 90; int id = 90; // Abstract method (public and abstract by default) // Compiler Interpretation: public abstract void abstractMethod(); void abstractMethod(); // Default method - Introduced in Java 8 (public by default) // Compiler Interpretation: public default void concreteMethod() default void concreteMethod() { System.out.println("Concrete Method Called"); } // Static method - Introduced in Java 8 (public by default) // Compiler Interpretation: public static void staticMethod() static void staticMethod() { System.out.println("Static Method Called"); } }
Même avec les méthodes par défaut, les interfaces restent distinctes des classes abstraites :
Aspect | Interface | Abstract Class |
---|---|---|
Methods | Can have abstract, default, and static methods | Can have abstract and non-abstract methods |
Variables | Only public, static, and final variables | Can have any access modifier and instance variables |
Inheritance | Supports multiple inheritance | Supports single inheritance |
Constructors | Cannot have constructors | Can have constructors |
Les méthodes par défaut doivent être utilisées uniquement pour étendre les interfaces existantes où une compatibilité ascendante est nécessaire. Ils ne remplacent pas les cours abstraits.
1. Une variable d'interface peut-elle être modifiée ?
Non, les variables d'interface sont implicitement finales, ce qui signifie que leur valeur ne peut pas être modifiée une fois attribuée.
package oops.interfaces; public interface InterfaceBasics { // Variables are public, static, and final by default // Initialization can only be done with declaration (No Static Blocks) // Compiler Interpretation: public static final int id = 90; int id = 90; // Abstract method (public and abstract by default) // Compiler Interpretation: public abstract void abstractMethod(); void abstractMethod(); // Default method - Introduced in Java 8 (public by default) // Compiler Interpretation: public default void concreteMethod() default void concreteMethod() { System.out.println("Concrete Method Called"); } // Static method - Introduced in Java 8 (public by default) // Compiler Interpretation: public static void staticMethod() static void staticMethod() { System.out.println("Static Method Called"); } }
2. Pouvons-nous déclarer une méthode à la fois par défaut et statique ?
Non. Une méthode par défaut fournit une implémentation concrète qui peut être remplacée par l'implémentation de classes, permettant une flexibilité. En revanche, une méthode statique appartient à l'interface elle-même, ne peut pas être remplacée et offre des fonctions utilitaires. Ainsi, les deux ne peuvent pas être utilisés ensemble.
package oops.interfaces; // A class implementing the InterfaceBasics interface public class InterfaceBasicsImpl implements InterfaceBasics { // Mandatory: Override all abstract methods from the interface @Override public void abstractMethod() { System.out.println("Overridden Method Called"); } public static void main(String[] args) { InterfaceBasics obj = new InterfaceBasicsImpl(); // Calling interface's default and overridden methods obj.concreteMethod(); // Output: Default Method Called obj.abstractMethod(); // Output: Overridden Method Called // Accessing interface variables (static and final by default) // Interface variables are inherited // Possible with both interface name and implementing class name System.out.println(InterfaceBasics.id); // Output: 90 System.out.println(InterfaceBasicsImpl.id); // Output: 90 // Cannot assign a value to final variable 'id' InterfaceBasicsImpl.id = 100; // --> Compile Error // Calling static method using interface name // Cannot access using implementing class name // Interface static methods are NOT inherited InterfaceBasics.staticMethod(); // Output: Static Method Called } }
3. Pourquoi les méthodes statiques dans les interfaces ne peuvent-elles pas être héritées ?
Les méthodes statiques sont associées à l'interface elle-même plutôt qu'à toute instance spécifique d'une classe, ce qui signifie qu'elles appartiennent à l'interface dans son ensemble. Si les méthodes statiques étaient héritées des classes d'implémentation, cela pourrait conduire à ambiguïté et confusion quant à la méthode appelée, surtout si plusieurs interfaces définissent des méthodes portant le même nom.
Par exemple :
package oops.interfaces.example; public interface Logger { // Using a variable to store the default log file name String DEFAULT_LOG_FILE_NAME = "application.log"; // Static method to get the default log file name with configuration static String getDefaultLogFileName() { // Simulating configuration retrieval // Could be from a properties file or environment variable String logFileName = System.getenv("LOG_FILE_NAME"); // If a log file name is set in the environment, return it; // Otherwise, return the default if (logFileName != null && !logFileName.isEmpty()) { return logFileName; } else { return DEFAULT_LOG_FILE_NAME; } } } public class FileLogger implements Logger { public static void main(String[] args) { // Using the interface variable String defaultLogFile = Logger.DEFAULT_LOG_FILE_NAME; // Using the static method if ("FILE".equals(System.getenv("LOG_TYPE"))) { defaultLogFile = Logger.getDefaultLogFileName(); } System.out.println("Log file used: " + defaultLogFile); } }
En gardant les méthodes statiques liées uniquement à l'interface, Java maintient la clarté et évite les conflits potentiels dans la résolution des méthodes conduisant au infâme problème de diamant de l'héritage multiple.
Les interfaces en Java jouent un rôle crucial dans la réalisation de l'abstraction en définissant le comportement auquel les classes d'implémentation doivent adhérer. Avec l'introduction des méthodes par défaut et des méthodes statiques dans Java 8, les interfaces sont devenues encore plus puissantes, permettant une compatibilité ascendante et fournissant des méthodes utilitaires directement dans les interfaces.
Cependant, les interfaces ne remplacent pas les classes abstraites. Ils doivent être utilisés lorsque vous devez définir un contrat pour le comportement, en particulier lorsque un héritage multiple est requis.
Interfaces fournissent une abstraction en définissant ce qu'une classe doit faire, sans préciser comment.
Variables dans les interfaces sont toujours publiques, statiques et finales.
Méthodes par défaut et statiques, introduites dans Java 8, permettent une compatibilité ascendante et des implémentations d'utilitaires au sein des interfaces.
Les méthodes statiques dans les interfaces ne sont pas héritées, ce qui garantit la clarté de leur utilisation.
Comprendre comment et quand utiliser les interfaces améliorera non seulement vos compétences en codage, mais vous préparera également aux questions d'entretien autour des concepts POO et des modèles de conception Java.
Principes fondamentaux de Java
Les essentiels de l'entretien avec Array
L'essentiel de la mémoire Java
L'essentiel des mots-clés Java
L'essentiel du cadre de collections
Bon codage !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!