¿Por qué todos los campos de una interfaz son implícitamente estáticos y finales?

100

Solo estoy tratando de entender por qué todos los campos definidos en una interfaz son implícitamente staticy final. La idea de mantener campos statictiene sentido para mí, ya que no puede tener objetos de una interfaz, pero ¿por qué lo son final(implícitamente)?

¿Alguien sabe por qué los diseñadores de Java optaron por crear los campos en una interfaz staticy final?

pico
fuente
Para una nota para mí: es estático porque los campos de la interfaz no se convertirán en parte del objeto que lo implementa.
Lloviendo

Respuestas:

126

Una interfaz no puede tener comportamiento o estado porque está destinada a especificar solo un contrato de interacción, sin detalles de implementación. 'Sin comportamiento' se aplica al no permitir cuerpos de método / constructor o bloques de inicialización estáticos / de instancia. 'Ningún estado' se aplica permitiendo solo campos finales estáticos. Por lo tanto, la clase puede tener un estado (estado estático), pero la interfaz no infiere el estado de la instancia.

Por cierto: una constante en Java se define mediante un campo final estático (y por convención el nombre usa UPPER_CASE_AND_UNDERSCORES).

Adriaan Koster
fuente
54
No es necesariamente cierto que los campos finales sean constantes; eso solo está garantizado para tipos primitivos. En general, la palabra clave final simplemente significa que la ubicación de la memoria no cambiará.
Pops
8
No dije que los campos finales son constantes, solo que las constantes son campos finales. Tenga en cuenta que se permite poner un campo final estático no primitivo en una interfaz. Aunque el contenido de ese campo pueda cambiar, la referencia a él es constante.
Adriaan Koster
1
@AdriaanKoster Dijiste exactamente que el campo final es constante: ningún estado se aplica al permitir solo constantes. - esta oración implica que todos los campos finales son constantes. Puede intentar discutir más sobre las palabras que utilizó, pero obviamente su declaración es al menos engañosa.
Tomáš Zato - Reincorpora a Monica
2
Debe ser mi intelecto menguante, pero después de seis años de mirar esta respuesta, que resulta ser mi respuesta de mayor puntuación, todavía no entiendo los comentarios. Sugiera una redacción diferente porque no veo nada incorrecto.
Adriaan Koster
Podría haber sido la intención de los diseñadores de Java convertir una interfaz sin estado, pero fallaron porque un campo de instancia puede ser una clase modificable. En lugar de admitir que fallaron, eligen forzar los campos de instancia static final, que es lo más cercano a lo real (siendo real C / C ++) constcomo se puede obtener en Java. Desafortunadamente, esto está implícito y puede generar confusión para los no expertos. (Me acabo de dar cuenta de que lo son staticporque observé un comportamiento no deseado. Aprendí que son finalsolo de esta respuesta).
not-a-user
27

Razón de ser final

Cualquier implementación puede cambiar el valor de los campos si no están definidos como finales. Entonces se convertirían en parte de la implementación. Una interfaz es una especificación pura sin ninguna implementación.

Razón de ser static

Si son estáticos, pertenecen a la interfaz, y no al objeto, ni al tipo de tiempo de ejecución del objeto.

Gurpreet singh sidhuu
fuente
18

Hay un par de puntos que se pasan por alto aquí:

El hecho de que los campos en una interfaz sean implícitamente estáticos finales no significa que deban ser constantes en tiempo de compilación, o incluso inmutables. Puede definir, por ejemplo,

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(Tenga en cuenta que hacer esto dentro de una definición de anotación puede confundir a javac , en relación con el hecho de que lo anterior en realidad se compila en un inicializador estático).

Además, la razón de esta restricción es más estilística que técnica, y a mucha gente le gustaría verla relajada .

Jesse Glick
fuente
9

Los campos deben ser estáticos porque no pueden ser abstractos (como pueden hacerlo los métodos). Debido a que no pueden ser abstractos, los implementadores no podrán proporcionar lógicamente la implementación diferente de los campos.

Los campos deben ser definitivos, creo, porque muchos implementadores diferentes pueden acceder a los campos, lo que permite que se puedan cambiar y puede ser problemático (como la sincronización). También para evitar que se vuelva a implementar (ocultar).

Solo mi pensamiento.

NawaMan
fuente
NawMan, tu explicación sobre "Los campos deben ser estáticos ..." no tiene mucho sentido. Pero tenías mucha razón sobre "Los campos deben ser definitivos ..."
pico del
1
No creo que tenga razón sobre la razón por la que los campos deben ser definitivos. Permitir que diferentes implementadores cambien un campo no es problemático, ya que de lo contrario la herencia sería problemática. Los campos deben ser definitivos, como dijo Adriaan, porque una interfaz es y debe ser sin estado. Una interfaz con un estado debería ser básicamente una clase abstracta.
Axelle Ziegler
Si tiene un public staticcampo que no lo es final, findbugs se quejará (¡con razón!).
Tom Hawtin - tackline
2

Considero que el requisito de que los campos sean finales es excesivamente restrictivo y un error de los diseñadores del lenguaje Java. Hay ocasiones, por ejemplo, en el manejo de árboles, en las que es necesario establecer constantes en la implementación que son necesarias para realizar operaciones en un objeto del tipo de interfaz. Seleccionar una ruta de código en la clase de implementación es un fastidio. La solución alternativa que utilizo es definir una función de interfaz e implementarla devolviendo un literal:

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

Sin embargo, sería más simple, más claro y menos propenso a una implementación aberrante usar esta sintaxis:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}
Carl Klapper
fuente
Parece que se queja más de que los campos son estáticos que finales.
Daniel Yankowsky
0

Especificación, contratos ... La instrucción de la máquina para el acceso al campo utiliza la dirección del objeto más el desplazamiento del campo. Dado que las clases pueden implementar muchas interfaces, no hay forma de hacer que el campo de interfaz no final tenga el mismo desplazamiento en todas las clases que extienden esta interfaz. Por lo tanto, se debe implementar un mecanismo diferente para el acceso al campo: dos accesos a la memoria (obtener el desplazamiento del campo, obtener el valor del campo) en lugar de uno más el mantenimiento de una especie de tabla de campo virtual (análogo de la tabla de método virtual). Supongo que simplemente no querían complicar jvm para una funcionalidad que se puede simular fácilmente a través de cosas (métodos) existentes.

En scala podemos tener campos en interfaces, aunque internamente se implementan como expliqué anteriormente (como métodos).

Yaroslav
fuente
-1

static:

Cualquier cosa (variable o método) que esté staticen Java se puede invocar como Classname.variablenameoClassname.methodname bien directamente. No es obligatorio invocarlo solo utilizando el nombre del objeto.

En la interfaz, los objetos no se pueden declarar y statichace posible invocar variables solo a través del nombre de la clase sin la necesidad del nombre del objeto.

final:

Ayuda a mantener un valor constante para una variable, ya que no se puede anular en sus subclases.

Sabika
fuente