¿Por qué las variables de interfaz son estáticas y finales por defecto?


274

¿Por qué las variables de interfaz son estáticas y finales por defecto en Java?


41
No debe poner ninguna variable dentro de las interfaces.
Cherouvim

34
Porque las interfaces definen contratos que se pueden implementar de varias maneras. El valor de una variable es la implementación.
cherouvim

10
Ciertamente, cuando sabemos que todas las clases que implementan la interfaz tienen algunas variables constantes (nombres de campo, por ejemplo).
Aniket Thakur

¿Es una buena idea hacer que una variable en una clase sea una instancia de la interfaz que implementa la clase? He escuchado esto antes.
Doug Hauf

Las interfaces en Java siguen el principio ACID, final debido a la normalización en C. @cherouvim El tipo de una variable es la implementación, una variable debe declararse, con o sin un valor y la definición de una variable es el valor. Si cambia el valor de una variable no es reimplementación, es redefinición.
Grim

Respuestas:


264

Desde el diseño de la interfaz Java Preguntas frecuentes por Philip Shaw:

Las variables de interfaz son estáticas porque las interfaces de Java no se pueden instanciar por derecho propio; El valor de la variable debe asignarse en un contexto estático en el que no exista ninguna instancia. El modificador final asegura que el valor asignado a la variable de interfaz es una constante real que no puede ser reasignada por el código del programa.

fuente


39
Tenga en cuenta que las clases abstractas no se pueden instanciar "por derecho propio" tampoco y que pueden tener variables de instancia.
macias

18
Esta explicación para el staticmodificador es completamente espuria. Las variables de instancia pública de una clase son parte de su interfaz y no hay razón para que no se abstraigan en Java interface, al igual que los métodos de instancia. No importa que un Java interfaceno pueda ser instanciado directamente; aún puede tener instancias de clases que implementen interfacey es sensato exigir que tengan una determinada variable de instancia pública. En cuanto a la parte sobre final, eso no ofrece una explicación en absoluto, solo describe lo que finalsignifica.
Pyrocrasty

3
La cita anterior es mejor en contexto. La razón que da es que "las variables de interfaz están destinadas a ser constantes de Java". La cita solo explicaba por qué esa constante sería estática y final. Eso es cierto, pero la verdadera pregunta es: ¿por qué no se permiten variables como parte de la interfaz real (es decir, especificar los nombres y tipos de miembros no privados que deben ocurrir en una clase de implementación)? Si quisieran "constantes de interfaz" especiales, podrían haber usado una nueva sintaxis, o simplemente haber decidido que cualquier variable realmente definida en una interfaz son constantes de interfaz.
Pyrocrasty

66
Las interfaces no pueden tener variables de instancia para evitar la herencia múltiple de problemas de estado. Ver docs.oracle.com/javase/tutorial/java/IandI/… . Una clase no puede extender más de una clase debido a la misma razón.
denis

1
¿Cómo se introducen los métodos predeterminados y si tienen instancia? Sin embargo, la variable de instancia no es compatible ...
M.kazem Akhgary

41

Dado que la interfaz no tiene un objeto directo, la única forma de acceder a ellos es mediante el uso de una clase / interfaz y, por lo tanto, si existe una variable de interfaz, debería ser estática; de lo contrario, no será accesible para el mundo exterior. Ahora, dado que es estático, solo puede contener un valor y cualquier clase que lo implemente puede cambiarlo y, por lo tanto, será todo un desastre.

Por lo tanto, si existe una variable de interfaz, será implícitamente estática, final y obviamente pública.


Por supuesto, una variable de instancia sería accesible si se permitiera en un Java interface. Una clase implementaría la interfaz, declarando la variable de instancia (como lo requiere la interfaz). Su constructor (u otro método) establece la variable de instancia. Cuando se instancia una instancia de la clase, podrá acceder a su variable de instancia.
Pyrocrasty

Java permite que existan métodos estáticos con cuerpos en una interfaz. Esos podrían acceder a las variables estáticas. Simplemente no pueden cambiarlos, lo que significa que las funciones estáticas no pueden almacenar ningún dato
simpleuser

36

public : para la accesibilidad en todas las clases, al igual que los métodos presentes en la interfaz

static : como la interfaz no puede tener un objeto, se puede usar interfaceName.variableName para hacer referencia a él o directamente el variableName en la clase que lo implementa.

final : hacerlos constantes. Si 2 clases implementan la misma interfaz y les da a ambos el derecho de cambiar el valor, se producirá un conflicto en el valor actual de la var, por lo que solo se permite la inicialización de una vez.

Además, todos estos modificadores están implícitos para una interfaz, realmente no necesita especificar ninguno de ellos.


15

( Esta no es una respuesta filosófica, sino más práctica ). El requisito del staticmodificador es obvio y ha sido respondido por otros. Básicamente, dado que las interfaces no se pueden instanciar, la única forma de acceder a sus campos es convertirlos en un campo de clase static.

La razón por la que los interfacecampos se vuelven automáticamente final(constantes) es para evitar que diferentes implementaciones cambien accidentalmente el valor de la variable de interfaz que puede afectar inadvertidamente el comportamiento de las otras implementaciones. Imagine el siguiente escenario en el que una interfacepropiedad no se convirtió explícitamente en finalJava:

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

Ahora, piense qué sucedería si otra clase que implementa Actionablealtera el estado de la variable de interfaz:

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

Si un cargador de clases carga estas clases dentro de una sola JVM, entonces el comportamiento de NuclearActionpuede verse afectado por otra clase CleanAction, cuando performAction()se invoca después CleanActionde que se ejecuta (en el mismo hilo o de otro modo), que en este caso puede ser desastroso (semánticamente eso es).

Como no sabemos cómo cada implementación de un interfaceva a utilizar estas variables, deben serlo implícitamente final.


9

Porque cualquier otra cosa es parte de la implementación, y las interfaces no pueden contener ninguna implementación.


1
Entonces, ¿cuál es el motivo de la final.
Jothi

77
Para indicar que es una constante. Java no tiene una palabra clave const. estática final es cómo declaras constantes.
Amir Afghani el

55
Desde Java 8, pueden contener una implementación, pero se recomienda encarecidamente no usarla si no necesita compatibilidad con backwarts. :)
codepleb

6
public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

Aquí está la solución.

System.out.println(A.x); // done

Creo que es la razón por la cual las variables de interfaz son estáticas.

No declare variables dentro de la interfaz.


3
De hecho, sin la especificación "Axe" ni siquiera se compilaría ", por lo que es realmente seguro usar variables (que implícitamente son estáticas públicas finales) en las interfaces.
Marco

No estoy de acuerdo con la respuesta, ya que @Marco dijo que ni siquiera se compilaría. No encontré ninguna otra desventaja hasta ahora, tal vez solo que no se ve escrito static finalantes de la variable que en realidad es estática y final.
Micer

5

estática, porque la interfaz no puede tener ninguna instancia. y final, porque no necesitamos cambiarlo.


15
"no necesitamos" == "no se nos permite", no mezcle los significados.
peterh - Restablece a Monica

3

porque:

Static : como no podemos tener objetos de interfaces, debemos evitar el uso de variables miembro de nivel de objeto y debemos usar variables de nivel de clase, es decir, estático.

Final : para que no debamos tener valores ambiguos para las variables (problema de Diamante - Herencia múltiple).

Y según la interfaz de documentación es un contrato y no una implementación.

referencia: la respuesta de Abhishek Jain sobre quora


2

Java no permite variables abstractas y / o definiciones de constructor en las interfaces. Solución: simplemente cuelgue una clase abstracta entre su interfaz y su implementación que solo extiende la clase abstracta de la siguiente manera:

 public interface IMyClass {

     void methodA();
     String methodB();
     Integer methodC();

 }

 public abstract class myAbstractClass implements IMyClass {
     protected String varA, varB;

     //Constructor
     myAbstractClass(String varA, String varB) {
         this.varA = varA;
         this.varB = VarB;
     }

     //Implement (some) interface methods here or leave them for the concrete class
     protected void methodA() {
         //Do something
     }

     //Add additional methods here which must be implemented in the concrete class
     protected abstract Long methodD();

     //Write some completely new methods which can be used by all subclasses
     protected Float methodE() {
         return 42.0;
     }

 }

 public class myConcreteClass extends myAbstractClass {

     //Constructor must now be implemented!
     myClass(String varA, String varB) {
         super(varA, varB);
     }

     //All non-private variables from the abstract class are available here
     //All methods not implemented in the abstract class must be implemented here

 }

También puede usar una clase abstracta sin ninguna interfaz si está SEGURO de que no desea implementarla junto con otras interfaces más adelante. Tenga en cuenta que no puede crear una instancia de una clase abstracta, DEBE extenderla primero.

(La palabra clave "protegida" significa que solo las clases extendidas pueden acceder a estos métodos y variables).

spyro



1

Interfaz: Servicio de requisitos del sistema.

En la interfaz, las variables se asignan de manera predeterminada mediante un modificador de acceso final público, estático . Porque :

public: A veces sucede que la interfaz puede colocarse en otro paquete. Por lo tanto, debe acceder a la variable desde cualquier parte del proyecto.

estática: Como tal, la clase incompleta no puede crear objetos. Entonces, en el proyecto necesitamos acceder a la variable sin objeto para poder acceder con la ayuda deinterface_filename.variable_name

final: supongamos que una clase se implementa por muchas clases y todas las clases intentan acceder y actualizar la variable de la interfaz. Por lo tanto, genera inconsistencia en el cambio de datos y afecta a todas las demás clases. Por lo tanto, debe declarar el modificador de acceso con final.


0

En Java, la interfaz no le permite declarar ninguna variable de instancia. El uso de una variable declarada en una interfaz como variable de instancia devolverá un error de tiempo de compilación.

Puede declarar una variable constante, utilizando static finalcuál es diferente de una variable de instancia.


Esto es completamente incorrecto. El compilador no se quejará a menos que lo haga privado o protegido. Bajo el capó, como otros ya han mencionado, se convierten en público estático final. Y supongo que es bastante obvio por qué. Porque la interfaz está destinada a dictar el comportamiento, no el estado.
Mikayil Abdullayev

0

La interfaz puede ser implementada por cualquier clase y si ese valor se modifica por una de las clases implementadoras, habrá engaño para otras clases implementadoras. La interfaz es básicamente una referencia para combinar dos entidades coreladas pero diferentes. Por lo tanto, la variable de declaración dentro de la interfaz será implícitamente final y también estática porque la interfaz no puede ser instanciada.


0

Piense en una aplicación web donde tiene una interfaz definida y otras clases la implementan. Como no puede crear una instancia de interfaz para acceder a las variables, debe tener una palabra clave estática. Dado que es estático, cualquier cambio en el valor se reflejará en otras instancias que lo hayan implementado. Entonces, para evitarlo, los definimos como finales.


0

Acabo de probar en Eclipse, la variable en la interfaz es predeterminada para ser final, por lo que no puede cambiarla. En comparación con la clase padre, las variables son definitivamente cambiables. ¿Por qué? Desde mi punto de vista, la variable en clase es un atributo que será heredado por los niños, y los niños pueden cambiarlo según su necesidad real. Por el contrario, la interfaz solo define el comportamiento, no el atributo. La única razón para poner variables en la interfaz es usarlas como consts relacionadas con esa interfaz. Sin embargo, esta no es una buena práctica según el siguiente extracto:

"Colocar constantes en una interfaz era una técnica popular en los primeros días de Java, pero ahora muchos lo consideran un uso desagradable de las interfaces, ya que las interfaces deben tratar con los servicios proporcionados por un objeto, no sus datos. Además, las constantes utilizadas por clase son típicamente un detalle de implementación, pero colocarlos en una interfaz los promueve a la API pública de la clase ".

También intenté poner estática o no hacer ninguna diferencia. El código es el siguiente:

public interface Addable {
    static int count = 6;

    public int add(int i);

}

public class Impl implements Addable {

    @Override
    public int add(int i) {
        return i+count;
    }
}

public class Test {

    public static void main(String... args) {
        Impl impl = new Impl();

        System.out.println(impl.add(4));
    }
}
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.