tag standard library lib importar funciones abs java reference this variable-assignment

standard - ¿Por qué no se permite la asignación a ''esto'' en java?



jstl java standard tag library (7)

¿Son las razones técnicas o conceptuales?

OMI, conceptual.

La palabra clave this es una mano corta para "la referencia al objeto cuyo método está ejecutando actualmente". No puedes cambiar lo que es ese objeto. Simplemente no tiene sentido en el modelo de ejecución de Java.

Como no tiene sentido que this cambie, no tiene sentido convertirlo en una variable.

(Tenga en cuenta que en C ++ le está asignando *this , no this . Y en Java no hay * operador y no hay un equivalente real para él).

Si considera que podría cambiar el objeto de destino para un método en medio vuelo, aquí hay algunas preguntas contrarias.

  • ¿De qué sirve hacer esto? ¿Qué problemas le ayudaría a resolver esta característica lingüística (hipotética) ... que no puede resolverse de una manera más fácil de entender?

  • ¿Cómo trataría usted con mutexes? Por ejemplo, ¿qué pasaría si asignara this a la mitad de un método sincronizado ... y tiene sentido la propuesta semántica? (El problema es que terminas ejecutando en un método sincronizado en un objeto en el que no tienes un bloqueo ... o tienes que desbloquear el antiguo this y bloquear el nuevo this con las complicaciones que eso conlleva. Y además , ¿qué sentido tiene esto en términos de qué mutexes están diseñados para lograr?)

  • ¿Cómo darías sentido a algo como esto?

    class Animal { foo(Animal other) { this = other; // At this point we could be executing the overridden // Animal version of the foo method ... on a Llama. } } class Llama { foo(Animal other) { } }

    Claro que puedes atribuirle una semántica a esto pero:

    • ha roto la encapsulación de la subclase de una manera que es difícil de entender, y
    • En realidad no has logrado nada particularmente útil.

Si intenta responder seriamente estas preguntas, espero que llegue a la conclusión de que hubiera sido una mala idea implementar esto. (Pero si tiene respuestas satisfactorias, lo aliento a que las escriba y las publique como su propia respuesta a su pregunta).

Pero en realidad, dudo que los diseñadores de Java incluso consideraran esta idea más de un momento. (Y con razón, IMO)

La forma *this = ... de C ++ es realmente una abreviatura de una secuencia de asignaciones de los atributos del objeto actual. Ya podemos hacer eso en Java ... con una secuencia de tareas normales. Ciertamente no hay necesidad de una nueva sintaxis para apoyar esto. (¿Con qué frecuencia se reinicializa una clase del estado de otra clase?)

Observo que usted ha comentado así:

Me pregunto cuál es la semántica de this = xy; debiera ser. ¿Qué crees que debería hacer? - JimmyB Nov 2 ''11 a las 12:18

Si xy es del tipo correcto, la referencia de esto se establecería en xy , haciendo que el objeto "original" sea elegible para gc - kostja 2 de noviembre de 2011 a las 12:24

Eso no funcionará.

  1. El valor de this pasa (efectivamente) por valor al método cuando se invoca el método. La persona que llama no sabe de dónde viene this referencia.

  2. Incluso si lo hiciera, ese es solo un lugar donde se mantiene la referencia. A menos que se asigne null en todos los lugares, el objeto no puede ser elegible para la recolección de basura.

Ignorando el hecho de que esto es técnicamente imposible, no creo que su idea sea útil O propicia para escribir código legible / mantenible. Considera esto:

public class MyClass { public void kill(MyClass other) { this = other; } } MyClass mine = new MyClass(); .... mine.kill(new MyClass()); // ''mine'' is now null!

¿Por qué querrías hacer eso? Suponiendo que el nombre del método fuera algo inocuo en lugar de kill , ¿ esperaría usted que el método pudiera afectar mi valor?

Yo no. De hecho, creo que esto sería un error: inútil y peligroso.

Incluso sin estas semánticas desagradables de "hazlo inalcanzable", no veo ningún buen caso de uso para modificar this .

El error que recibo del compilador es "El lado izquierdo de una asignación debe ser una variable". Mi caso de uso es una copia profunda, pero no es realmente relevante.

En C ++, se puede asignar a *this .

La pregunta no es cómo sortear la asignación a this . Es muy simple, pero más bien, ¿cuál es la razón detrás de la decisión de no convertir this una variable?

¿Son las razones técnicas o conceptuales?

Mi conjetura hasta ahora: la posibilidad de reconstruir un Objeto en un método aleatorio es propensa a errores (conceptual), pero técnicamente es posible.

EDITAR Por favor, absténgase de las variaciones de "porque las especificaciones de java lo dicen". Me gustaría saber el motivo de la decisión.


En C ++, uno puede asignar a *this

Sí, pero no puedes hacer this = something en C ++, que realmente creo que es una coincidencia más cercana para lo que estás preguntando en el lado de Java aquí.

[...] qué razones hay detrás de la decisión de no convertir this una variable.

Yo diría claridad / legibilidad.

this fue elegida para ser una palabra reservada, probablemente ya que no se pasa como un argumento explícito a un método. Si se usa como un parámetro ordinario y se le puede reasignar un nuevo valor, se perdería la legibilidad.

De hecho, muchas personas argumentan que no debería cambiar las variables de argumento en absoluto, por esta misma razón.

¿Son las razones técnicas o conceptuales?

Principalmente conceptual presumiría. Sin embargo, surgirían algunas peculiaridades técnicas. Si pudiera reasignar un valor a this , podría ocultar completamente las variables de instancia detrás de las variables locales, por ejemplo.

Mi conjetura hasta ahora: la posibilidad de reconstruir un Objeto en un método aleatorio es propensa a errores (conceptual), pero técnicamente es posible.

No estoy seguro de entender completamente esta declaración, pero sí, el error propenso es probablemente la razón principal detrás de la decisión de convertirla en una palabra clave y no en una variable.


Asignar a *this en C ++ no es equivalente a asignar this en Java. Asignar this es, y no es legal en ninguno de los dos idiomas.


El this en Java es una parte del lenguaje, una palabra clave, no una variable simple. Fue hecho para acceder a un objeto desde uno de sus métodos, no otro objeto. Asignarle otro objeto causaría un desastre. Si desea guardar otra referencia de objetos en su objeto, simplemente cree una nueva variable.

La razón es sólo conceptual. this se hizo para acceder a un objeto en sí mismo, por ejemplo, para devolverlo en un método. Como dije, causaría un desastre si le asignaras otra referencia. Dime una razón por la que alterar this tendría sentido.


La asignación a (*this) en C ++ realiza una operación de copia, tratando el objeto como un tipo de valor .

Java no usa el concepto de un tipo de valor para las clases. La asignación de objetos es siempre por referencia .

Para copiar un objeto como si fuera un tipo de valor: ¿Cómo copio un objeto en Java?

Sin embargo, la terminología utilizada para Java es confusa: es Java "paso por referencia" o "paso por valor"

Respuesta: Java pasa referencias por valor. (desde here )

En otras palabras, dado que Java nunca trata los no primitivos como tipos de valor, cada variable de tipo de clase es una referencia (de hecho, un puntero).

Entonces, cuando digo "la asignación de objetos siempre es una referencia", podría ser más técnicamente exacto decir que "la asignación de objetos siempre es por el valor de la referencia".

La implicación práctica de la distinción hecha por Java que siempre se pasa por valor está incorporada en la pregunta " ¿Cómo puedo hacer que mi función de intercambio en java? ", Y su respuesta: No puedes . Los lenguajes como C y C ++ pueden proporcionar funciones de intercambio porque, a diferencia de Java, le permiten asignar desde cualquier variable usando una referencia a esa variable, lo que le permite cambiar su valor (si no es constante) sin cambiar la Contenidos del objeto al que hacía referencia anteriormente.

Podría hacer que tu cabeza gire para tratar de pensar en todo esto, pero aquí no va nada ...

  • Las variables de tipo de clase de Java son siempre "referencias" que son efectivamente punteros.
  • Los punteros de Java son tipos primitivos.
  • La asignación de Java es siempre por el valor de la primitiva subyacente (el puntero en este caso).
  • Java simplemente no tiene un mecanismo equivalente al paso por referencia de C / C ++ que le permita modificar indirectamente un tipo primitivo independiente, que puede ser un "puntero" como this .

Además, es interesante observar que C ++ en realidad tiene dos sintaxis diferentes para el paso por referencia. Uno se basa en punteros explícitos y se heredó del lenguaje C. El otro se basa en el operador de tipo de referencia C ++ & . [También existe la forma de puntero inteligente de C ++ de la gestión de referencias, pero eso es más parecido a la semántica similar a Java, donde las referencias se pasan por valor]

Nota: En la discusión anterior, asignar y pasar son terminología generalmente intercambiable. Subyacente a cualquier asignación, es una función de operador conceptual que realiza la asignación basada en el objeto del lado derecho que se pasa .

Así que volviendo a la pregunta original : si pudiera asignárselo a Java, eso implicaría cambiar el valor de la referencia que tiene. Eso es en realidad equivalente a asignarlo directamente en C ++, lo cual tampoco es legal en ese idioma.

Tanto en Java como en C ++, this es efectivamente un puntero que no se puede modificar. Java parece diferente porque usa el . operador para eliminar la referencia al puntero, que, si está acostumbrado a la sintaxis de C ++, le da la impresión de que no es una.

Por supuesto, puede escribir algo en Java que sea similar a un constructor de copia de C ++, pero a diferencia de C ++, no hay forma de evitar el hecho de que la implementación deberá proporcionarse en términos de una inicialización explícita de miembros. . [En C ++, puedes evitar esto, en última instancia, solo porque el compilador proporcionará una implementación del operador de asignación por parte de los miembros]

Sin embargo, la limitación de Java que no puedes copiar a todo esto es algo artificial. Puede lograr exactamente el mismo resultado escribiéndolo en forma de miembro, pero el lenguaje simplemente no tiene una forma natural de especificar la operación que se realizará en un this - la sintaxis de C ++, (*this) no Tener un análogo en Java. Y, de hecho, no hay una operación integrada en Java que reasigne el contenido de ningún objeto existente, incluso si no se lo denomina this . [Tal operación es probablemente más importante para los objetos basados ​​en la pila, como son comunes en C ++.]

Respecto al caso de uso de realizar una copia en profundidad : es complicado en Java .

Para C ++, un lenguaje orientado al tipo de valor. La intención semántica de asignación es generalmente obvia. Si digo a=b , normalmente quiero que se convierta en un clone independiente de b , que contenga un valor igual. C ++ hace esto automáticamente para la asignación , y hay plans para automatizar el proceso, también, para la comparación.

Para Java, y otros lenguajes orientados a referencias, copiar un objeto, en un sentido genérico, tiene un significado ambiguo. Aparte de los primitivos, Java no distingue entre tipos de valor y tipos de referencia , por lo que copiar un objeto debe considerar cada miembro de tipo de clase anidado (incluidos los del padre) y decidir, caso por caso, si ese objeto miembro debe ser copiado o solo referenciado. Si se deja a las implementaciones predeterminadas, existe una gran posibilidad de que el resultado no sea el deseado. La comparación de objetos por igualdad en Java sufre de las mismas ambigüedades .

Sobre la base de todo esto, la respuesta a la pregunta subyacente : ¿por qué no puedo copiar un objeto mediante una operación simple y generada automáticamente en this , es que , fundamentalmente, Java no tiene una idea clara de lo que significa copiar? un objeto

Un último punto, para responder a la pregunta literal:

¿Qué razón hay detrás de la decisión de no convertir this una variable?

Simplemente sería inútil hacerlo. El valor de this es solo un puntero que se ha pasado a una función, y si pudo cambiar el valor de this , no podría afectar directamente a ningún objeto, o referencia, se usó para invocar ese método. Después de todo, Java es pasar por valor.


this no es ni siquiera una variable. Es una palabra clave, como se define en la Especificación del lenguaje Java :

Cuando se usa como expresión primaria, la palabra clave esto denota un valor que es una referencia al objeto para el que se invocó el método de instancia (§15.12), o al objeto que se está construyendo.

Entonces, no es posible ya que no es posible asignar un valor a while .


porque this es final ,

this es una palabra clave, no una variable y no se puede asignar algo a la palabra clave. ahora para un mínimo, considere si se trata de una variable de referencia en las especificaciones de diseño ... y vea el ejemplo a continuación

y contiene una referencia implícita al método de llamada a objetos. y se usa solo como referencia, ahora considera que le asignas algo a this así que no lo romperá todo?

Ejemplo

considere el siguiente código de String clase String (Nota: el siguiente código contiene un error de compilación, es solo para demostrar OP la situación)

public CharSequence subSequence(int beginIndex, int endIndex) { //if you assign something here this = "XYZ" ; // you can imagine the zoombie situation here return this.substring(beginIndex, endIndex); }