¿Por qué no hay una característica constante en Java?


140

Estaba tratando de identificar la razón detrás de las constantes en Java. Aprendí que Java nos permite declarar constantes mediante el uso de finalpalabras clave.

Mi pregunta es por qué Java no introdujo una característica Constant ( const). Como muchas personas dicen que proviene de C ++, en C ++ tenemos constpalabras clave.

Por favor comparte tus pensamientos.


2
No es una constpalabra clave, pero no hay ninguna característica subyacente. Corregido su título y etiquetas en consecuencia.
Marqués de Lorne

Respuestas:


142

Cada vez que paso de la codificación C ++ pesada a Java, me lleva un tiempo adaptarme a la falta de corrección constante en Java. Este uso de consten C ++ es muy diferente a solo declarar variables constantes, si no lo sabía. Esencialmente, asegura que un objeto sea inmutable cuando se accede a él a través de un tipo especial de puntero llamado const-pointer. Cuando en Java, en lugares donde normalmente quisiera devolver un const-pointer, en su lugar devuelvo una referencia con un tipo de interfaz que contiene solo métodos que no deberían tener efectos secundarios. Desafortunadamente, esto no es impuesto por el idioma.

Wikipedia ofrece la siguiente información sobre el tema:

Curiosamente, la especificación del lenguaje Java considera a const como una palabra clave reservada, es decir, una que no se puede utilizar como identificador de variable, pero que no le asigna semántica. Se cree que la reserva de la palabra clave ocurrió para permitir una extensión del lenguaje Java para incluir métodos const de estilo C ++ y puntero al tipo const. El ticket de solicitud de mejora en el Proceso de la Comunidad Java para implementar la corrección constante en Java se cerró en 2005, lo que implica que la corrección constante probablemente nunca llegue a la especificación oficial de Java.


10
Sin finalembargo, Java es similar.
reinierpost

62
No, no lo es. finalmétodo, por ejemplo, funciona completamente diferente de los constmétodos de C ++ .
dom0

77
@reinierpost La finalpalabra clave en propiedades o variables solo garantiza que una propiedad o variable solo se asigne a una vez . Todavía se podría alterar el estado de este objeto, por ejemplo, llamando a algún método con efectos secundarios. finales algo similar a la asignación de pila de C ++ en términos de referirse a un objeto en lugar de un puntero, pero eso es todo. Esto es, por supuesto, además de lo que dom0 ya dijo.
Tim

9
finalen Java parece funcionar como C ++ constpara los tipos de valor, pero más como un C ++ no constante T&para los tipos de referencia
Mark K Cowan

1
final es una palabra clave esquizofrénica. Si bien evita la reasignación, también se usa para exponer variables a cierres. Es posible que desee evitar la reasignación pero no exponer esas variables, pero no hay forma de hacerlo. Es una característica del lenguaje bastante mal pensada en mi opinión.
David Bradley

82

Lo que constsignifica
Primero, date cuenta de que la semántica de una palabra clave "const" significa cosas diferentes para diferentes personas:

  • referencia de solo lectura - finalSemántica de Java - la variable de referencia en sí no puede reasignarse para que apunte a otra instancia (ubicación de memoria), pero la instancia en sí es modificable
  • referencia de solo lectura - C constpuntero / semántica de referencia - significa que esta referencia no se puede usar para modificar la instancia (por ejemplo, no se puede asignar a variables de instancia, no se pueden invocar métodos mutables) - solo afecta a la variable de referencia, por lo que una referencia no constante que apunta a la misma instancia podría modificar la instancia
  • objeto inmutable - significa que la instancia en sí no se puede modificar - se aplica a la instancia, por lo que no se permitiría ninguna referencia no constante o no se podría usar para modificar la instancia
  • alguna combinación de lo anterior ?
  • otros ?

Por qué o por qué no enconst
segundo lugar, si realmente quiere profundizar en algunos de los argumentos "pro" vs "con", consulte la discusión bajo este "error" de solicitud de mejora (RFE). Este RFE solicita una característica "const" de "referencia de solo lectura". Abierto en 1999 y luego cerrado / rechazado por Sun en 2005, el tema "constante" se debatió vigorosamente:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

Si bien hay muchos buenos argumentos en ambos lados, algunas de las razones más frecuentemente citadas (pero no necesariamente convincentes o claras) constincluyen:

  • puede tener una semántica confusa que puede ser mal utilizada y / o maltratada (vea lo que constsignifica arriba)
  • puede duplicar la capacidad disponible de otra manera (por ejemplo, diseñar una clase inmutable, usar una interfaz inmutable)
  • puede ser una característica de desplazamiento, lo que lleva a la necesidad de otros cambios semánticos, como el soporte para pasar objetos por valor

Antes de que alguien trate de debatirme si estas son buenas o malas razones, tenga en cuenta que estas no son mis razones . Son simplemente la "esencia" de algunas de las razones por las que deduje eludir la discusión sobre RFE. No estoy necesariamente de acuerdo con ellos, simplemente estoy tratando de mencionar por qué algunas personas (no yo) pueden sentir que una constpalabra clave puede no ser una buena idea. Personalmente, me encantaría que se introdujera más semántica "constante" en el lenguaje de una manera inequívoca.


2
+1 solo para la segunda parte de tu respuesta. Muchas palabras clave tienen una semántica no trivial. ¿Es volatiletan simple de entender? O final? Meh
einpoklum

OTOH, Java fue diseñado para usar la menor cantidad posible de esas características no triviales. Y no estoy diciendo que lograron ese objetivo (o que Java no se ha alejado de ese objetivo). Pero excluirlo por esa razón puede haber tenido mérito. Que hay otras cosas complicadas es una razón más para no introducir más (o terminarías con el lenguaje D).
Maarten Bodewes

7

const en C ++ no significa que un valor sea una constante.

const en C ++ implica que el cliente de un contrato se compromete a no alterar su valor.

Si el valor de una constexpresión cambia se hace más evidente si se encuentra en un entorno que admite concurrencia basada en subprocesos.

Como Java fue diseñado desde el principio para admitir subprocesos y bloquear la concurrencia, no aumentó la confusión al sobrecargar el término para tener la semántica que finaltiene.

p.ej:

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

salidas 42 y luego 7.

Aunque xmarcado como const, a medida que se crea un alias xno constante , no es una constante. No todos los compiladores requieren volatileeste comportamiento (aunque todos los compiladores pueden alinear la constante)

Con sistemas más complicados, obtienes alias const / non-const sin usar const_cast, por lo que adquirir el hábito de pensar que const significa que algo no cambiará se vuelve cada vez más peligroso. constsimplemente significa que su código no puede cambiarlo sin una conversión, no que el valor sea constante.


3
const int x = 42; - x es una constante

2
@Neil Si tiene un alias de objeto o variable con punteros constantes y no constantes, el alias no constante puede cambiar el valor del alias constante. Por constlo tanto , no significa que un valor sea constante. Significa que el cliente de un valor está obligado a no mutarlo. En su ejemplo no hay alias, por lo que todos los usuarios están bajo la misma restricción. Este no es el caso en general. constafecta a los clientes, no al valor: dice que no puede cambiarlo, no es que no cambie.
Pete Kirkham

1
La corrección correcta se trata de lo que debe hacer el programador , no de lo que puede hacer . Creo que todos parecen haber entendido ese punto. Solo quería agregar un par de centavos que podrían ser de interés para el lector causal: Diseñar patrones como immutable interfacey immutable objectes otra forma (superable con reparto y reflexión) para imitar const en Java. Const "verdadero" se puede hacer con SealedObject , por desgracia, destruye el caso de uso de nuestro objeto.
Martin Andersson

66
Hay que tener en cuenta que el resultado de su programa no está definido. const_cast no está ahí para cambiar las variables const, está ahí para pasar las variables const a las API que no son correctas const, pero tampoco modifican el valor. Creo que el hábito de pensar que algo const no cambiará es bueno porque si cambian, eso significa que su programa contiene hacks que podrían romperse en cualquier momento dependiendo del compilador utilizado.
Cygon

1
La modificación de un valor nacido a constante es un comportamiento indefinido. Es posible que su disco ya esté formateado.
Zhe Yang

5

Esta es una pregunta un poco vieja, pero pensé que contribuiría con mis 2 centavos de todos modos, ya que este hilo salió a la conversación hoy.

Esto no responde exactamente por qué no hay constante? pero cómo hacer que tus clases sean inmutables. (Desafortunadamente aún no tengo suficiente reputación para publicar como un comentario a la respuesta aceptada)

La forma de garantizar la inmutabilidad de un objeto es diseñar sus clases con más cuidado para que sean inmutables. Esto requiere un poco más de cuidado que una clase mutable.

Esto se remonta a la efectiva Java de Josh Bloch artículo 15 de : minimizar la mutabilidad . Si no ha leído el libro, tome una copia y léala varias veces. Le garantizo que mejorará su figurado "juego de Java" .

En el elemento 15, Bloch sugiere que debe limitar la mutabilidad de las clases para garantizar el estado del objeto.

Para citar el libro directamente:

Una clase inmutable es simplemente una clase cuyas instancias no se pueden modificar. Toda la información contenida en cada instancia se proporciona cuando se crea y se fija durante la vida útil del objeto. Las bibliotecas de la plataforma Java contienen muchas clases inmutables, incluidas String, las clases primitivas en caja y BigInteger y BigDecimal. Hay muchas buenas razones para esto: las clases inmutables son más fáciles de diseñar, implementar y usar que las clases mutables. Son menos propensos a errores y son más seguros.

Bloch luego describe cómo hacer que sus clases sean inmutables, siguiendo 5 reglas simples:

  1. No proporcione ningún método que modifique el estado del objeto (es decir, establecedores, también conocidos como mutadores )
  2. Asegúrese de que la clase no se pueda extender (esto significa declarar la clase como tal final).
  3. Hacer todos los campos final .
  4. Hacer todos los campos private .
  5. Garantice el acceso exclusivo a cualquier componente mutable. (haciendo copias defensivas de los objetos)

Para más detalles, recomiendo recoger una copia del libro.


3
const en C ++ es MUCHO más flexible que la inmutabilidad a gran escala. En cierto sentido, 'const' puede verse como 'inmutable dentro de este contexto particular'. Ejemplo: tengo una clase que no es inmutable, PERO quiero asegurarme de que no se modifique a través de ciertas API públicas. Hacer una interfaz (y devolverla para esa API pública) como sugiere Gunslinger47 logra lo mismo en Java, pero vaya, es feo (y, por lo tanto, es ignorado por la mayoría de los desarrolladores de Java, lo que lleva a un desorden innecesario significativo). .
No-bugs Hare

3

La semántica de C ++ constes muy diferente de Java final. Si los diseñadores lo hubieran usado const, habría sido innecesariamente confuso.

El hecho de que constsea ​​una palabra reservada sugiere que los diseñadores tenían ideas para implementar const, pero desde entonces han decidido no hacerlo; Mira este error cerrado . Las razones indicadas incluyen que agregar soporte para el estilo C ++ constcausaría problemas de compatibilidad.


-1

Hay una manera de crear variables "const" en Java, pero solo para clases específicas. Simplemente defina una clase con propiedades finales y subclasifíquela. Luego use la clase base donde quiera usar "const". Del mismo modo, si necesita utilizar métodos "const", agréguelos a la clase base. El compilador no le permitirá modificar lo que cree que son los métodos finales de la clase base, pero leerá y llamará a los métodos en la subclase.


¿Puedes dar algún ejemplo de esto, por favor?
NO_NAME el

la clase MYString implementa GetString {Private final String aaaa; public String getString (); } clase MutableString implementa GetString {private String aaaa2; public String getString (); public String setString ()}
user1122069

-2

Habría dos formas de definir constantes, consty static finalcon la misma semántica. Además static finaldescribe el comportamiento mejor queconst


@Bozho, dijiste mejor comportamiento que Const, ¿cómo es? ¿Puedes compartir algún ejemplo
gmhk

bueno, la variable es static(no perteneciente a una instancia particular) y final- no se puede cambiar.
Bozho

-2

Puede usar static final para crear algo que funcione de manera similar a Const, lo he usado en el pasado.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;

Votaron a favor de la optimización basada en rumores porque escuché un rumor de que esta es una estrategia ineficaz.
Afarley

Eliminé el rumor de la respuesta. aún puede usar static final int para crear código de estilo constante.
hamish 01 de

Ok, he eliminado mi voto negativo. Tal vez algunos de los demás downvotes son acerca de la instrucción switch (¿qué tiene que ver con el resto de su ejemplo?)
afarley

en la declaración de cambio usé el cRPM como si fuera una constante. bastante bien, teniendo en cuenta lo anterior. entonces sí, he quitado el interruptor.
hamish
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.