Si mi IDE es tan inteligente, ¿por qué necesito lanzar "clone ()"?

13

Mi tipo IDE ( NetBeans ) comprueba mi Collectionsmientras escribo código. Pero entonces, ¿por qué tengo que lanzar el objeto devuelto Object.clone()? Lo cual está bien. Sin daño no hay falta. Pero aún así, no entiendo.

¿Es posible la verificación de tipos, sin conversión, del objeto devuelto Object.clone()? El marco genérico me hace pensar que el IDE podría verificar el tipo de referencias a objetos en el lado derecho de la marca " = " sin emitir mientras escribo. No lo entiendo

Anexo
Mi caso de uso fue solo que tenía un Calendarcampo privado , pubdate . Yo iba a escribir:

Calendar getPubdate() {
    return pubdate;
}

pero existe el riesgo de que el invocador pueda modificar mi publicación , por lo que devolví una copia:

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

Entonces, me pregunté por qué necesitaba lanzar pubdate.clone(). La firma del método tiene el tipo allí mismo. NetBeans debería ser capaz de resolverlo. Y NetBeans parecía estar haciendo algo similar con respecto a Collections.

Konishiki
fuente
55
Un breve ejemplo de código (!) Sería útil.
Doc Brown
78
El IDE está separado del lenguaje en sí mismo, por lo que la inteligencia de Netbeans no tiene ningún efecto sobre cómo funciona Java.
JacquesB
77
Tenga en cuenta que, debido a la covarianza de tipo de retorno, se recomienda volver MyObjectdesde, en clone()lugar de Object, esto elimina todo este problema. Además, se recomienda no usar nunca clone()(Artículo efectivo de Java # 11).
Boris the Spider
¿El énfasis de su pregunta está en I o en 'cast "clone ()"' ? Porque la pregunta resultante de la primera podría ser una pregunta mucho mejor que la segunda.
user541686
Cuando leo el título de la pregunta, lo único en lo que pienso es this.clone()en el objeto del programador, especialmente en la noche del miércoles después del lanzamiento de Tue. Lo siento, pero tengo que escribir este comentario ... ¿Por qué el IDE inteligente no nos arregla todos los errores? LOL
Mai

Respuestas:

53

¿Por qué tengo que lanzar el objeto devuelto Object.clone()?

Porque vuelve Object.

El marco genérico me hace pensar que el IDE podría verificar el tipo de referencias a objetos en el lado derecho de la marca " = " sin emitir mientras escribo. No lo entiendo

Object.clone No es genérico.

Si los genéricos hubieran existido cuando clonese diseñó, probablemente se habría visto así (usando el polimorfismo limitado por F):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

Si Java tuviera una función MyType, quizás se vería así:

interface Cloneable {
  this clone();
}

Pero los genéricos no existían cuando Object.clonese diseñó, y Java no tiene MyTypes, por lo que la versión insegura de tipo Object.clonees con lo que tenemos que trabajar.

Jörg W Mittag
fuente
¿Acabo de darme cuenta de que la función IDE que me confundió fue la compilación en segundo plano? Quiero decir, ¿eso es lo que permite la finalización del código y la verificación automática de tipos con genéricos? Personalmente, preferiría retrasar la verificación de tipos hasta una compilación explícita. Pero me encanta completar el código.
konishiki
1
@konishiki con Java 8 (y en cierta medida Java 7) Tipo de inferencia , a fin de proporcionar cualquier tipo de asistencia, las necesidades IDE a tipos Deducir. Esto requiere una compilación parcial. Antes de la inferencia de tipos, no se necesita compilación para el autocompletado.
Boris the Spider
@BoristheSpider ¡Muchas gracias por sus comentarios! Definitivamente necesito hacer más pruebas / pensamiento. muy apreciado.
konishiki
¿Por qué necesitarías pasar original?
Clashsoft
@Clashsoft: Thinko estúpido mientras adapta la versión de programación funcional obvia. Gracias.
Jörg W Mittag
26

Esta no es una característica de ningún IDE, sino de la definición del lenguaje.

Un IDE lo ayuda a usar un lenguaje de programación de manera más eficiente, no cambia la semántica de ese lenguaje. Eso significa que un asistente de editor puede insertar automáticamente un reparto cuando sea obvio cuál desea, pero no puede simplemente romper las reglas del lenguaje y pretender que el código que no se compila es válido.

Editar Es cierto que un IDE puede agrupar su propio compilador, y de hecho muchos hacen exactamente eso, por ejemplo, para un mejor informe de errores con más información interna en el árbol de análisis parcial. Sin embargo, sería una muy mala idea dejar que este compilador interno implemente una semántica de lenguaje diferente que el SDK oficial, ya que eso significaría que el código que funciona en el desarrollo puede comenzar a fallar misteriosamente cuando se instala en producción, produciendo problemas que, por definición, no son depurable!

Kilian Foth
fuente
Esto es lo que sucedió: estoy bastante seguro de que la finalización del código es una función IDE (realizada mediante reflexión). Y la comprobación automática de tipos de la que hablaba ocurre en el IDE (a través de la compilación en segundo plano). Espero que eso sea lo que está pasando.
konishiki
1
El IDE puede romper fácilmente todas las reglas de la especificación del lenguaje y simplemente compilar el código de todos modos. Sé que NetBeans y Eclipse usan sus propios compiladores, por ejemplo. Entonces, en esos casos, IDE y el compilador son efectivamente la misma cosa. No digo que sea una buena idea, pero los compiladores de C ciertamente lo hacen todo el tiempo.
MichaelS
@MichaelS La especificación del lenguaje C está diseñada para permitir una variación significativa entre las implementaciones, de modo que diferentes proveedores puedan elegir entre diferentes enfoques posibles y agregar funciones adicionales. Esto crea varias áreas de ambigüedad en la especificación, que son necesarias para permitir esas variaciones. El nombre "C" no tiene marca registrada, por lo que nadie controla el uso del término. La especificación de Java está diseñada para eliminar la mayor ambigüedad posible, y Java es una marca registrada y el titular de la marca hace cumplir que solo puede usarse en implementaciones compatibles.
Jules
Los IDE modernos necesitan un compilador de todos modos. Las sugerencias de finalización de código requieren que se analice el código antes del cursor. Y ciertamente con genéricos (o plantillas de C ++) que requieren un compilador completo, no solo un analizador.
MSalters
3

Se debe a la firma de tipo del método Object.clone. La firma de tipo indica que el método devolverá un objeto de tipo Objeto.

protected Object clone() throws CloneNotSupportedException

Las colecciones utilizarán los llamados tipos genéricos para sustituir el tipo de conversión automáticamente.

Entonces, si tienes este código:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

el compilador agregará los moldes detrás de escena, por lo que el código en realidad sería:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);
Miró
fuente
0

Para completar, desde Java 5, se permiten tipos de retorno covariantes . Entonces puedes escribir lo siguiente:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

Con esto, el siguiente código es legal:

MyObject original = new MyObject();
MyObject clone = original.clone();
Olivier Grégoire
fuente