java compilation compiler-warnings deprecated suppress-warnings

java - ¿Cómo evitar las advertencias de desaprobación cuando @SuppressWarnings(“desaprobación”) no funciona?



compilation compiler-warnings (3)

Considere usar -Xmaxwarns, puede controlar cuántas advertencias antes de detener.

O intente recopilar el número de advertencias y fallar el proceso de integración, no compilar.

Por ejemplo: https://issues.apache.org/jira/browse/HADOOP-11252 . Cada código comprometido con el proyecto hadoop debe pasar el CI automatizado y dar -1 para aumentar el número de advertencias.

Tenemos un proyecto de Java. -Xlint las -Xlint (habilitar advertencias) y -Werror (tratar la advertencia como error) para javac , para asegurarnos de que nuestro código esté libre de advertencias. Recientemente decidimos dejar de lado una clase. El problema es que en algunos casos @SuppressWarnings("deprecation") no suprimirá la advertencia de desaprobación en absoluto, lo que resultará en un error de compilación. A continuación hay una lista de casos de uso que encontré:

  1. Importado en otras clases no en desuso.
  2. Importado en otras clases en desuso.
  3. Clase de padres
  4. Escriba el parámetro. Por ejemplo

    @SuppressWarnings("deprecation") public class Foo extends Bar<DeprecatedClass> { ... }

    Sin embargo, este no tiene ninguna advertencia, incluso sin suprimir:

    @Deprecated public class DeprecatedClass extends Bar<DeprecatedClass> { ... }

AFAIK, no hay sintaxis para anotar las importaciones, por lo que para el caso 1 y 2, nuestra solución es importar * o evitar la importación. Para los casos 3 y 4, tanto Java 6 como 7 no suprimen la advertencia. Java 8 lo suprimirá correctamente (quizás un error esté arreglado). Hasta ahora no hay solución para esto.

Desafortunadamente, tenemos que soportar Java 6, 7 y 8 en este punto. ¿Hay manera de lidiar con el problema? Es un obstáculo para nuestra evolución de la API de Java.

APÉNDICE

Mucha gente pregunta por qué seguimos usando la clase en desuso en nuestro propio código base. La razón es que el proyecto es una biblioteca, que admite muchos clientes diferentes. Al introducir una nueva API de reemplazo, primero debemos dejar de usar nuestra API anterior, mantenerla en nuestro código base, esperar a que todos los clientes migren y luego eliminarla. Hay tres casos de uso comunes:

  • Despreciamos la clase Foo y Bar , donde Foo extiende Bar . Este es el caso 2 y 3 en mi pregunta.
  • Despreciamos la clase Foo y Bar , donde Foo extiende la Collection<Bar> . Este es el caso 2 y 4.
  • Debemos mantener todos los códigos de prueba para la clase Foo y Bar . El código de prueba importa estas clases. Este es el caso 1.

¿Por qué mantener la prueba? No olvide que si se descubre un error grave (p. Ej., Pérdida de memoria, problema de seguridad) y los clientes no pueden migrar fácilmente a la nueva versión, todavía debemos proporcionar una solución a la antigua API. Y todos los cambios deben ser probados.

Creo que nuestra situación debería ser bastante común en el desarrollo de bibliotecas de software y la evolución de la API. Sorprendentemente, a Java le tomó tanto tiempo (hasta que Java 8) arreglar el error.


Lamento decir que no tengo una solución al problema que está enfrentando, aunque, como ha observado, ha habido algunos avances. Hemos estado tratando de deshacernos de todas las advertencias de compilación de Java en el propio JDK, y este ha sido un proceso largo y difícil. Durante el desarrollo de JDK 8 en 2011, ayudé a iniciar el esfuerzo de limpieza de las advertencias y luego presenté una charla sobre JavaOne ( diapositivas y audio ) sobre el tema.

Más recientemente, mi colega Joe Darcy ha continuado con el trabajo de limpieza de advertencias y ha trabajado en las diferentes categorías de advertencias y finalmente ha alcanzado las advertencias de desaprobación . Como notó, ha habido algunos errores en el manejo de la supresión de las advertencias de desaprobación por parte del compilador, como el JDK-6480588 que se corrigió en JDK 8. Desafortunadamente, en el JDK 8 no se pueden suprimir las advertencias sobre las importaciones de artículos obsoletos. Este error, JDK-8032211 , se solucionó bastante recientemente en nuestra línea de desarrollo JDK 9. De hecho, todavía estamos ajustando el manejo de la anotación @Deprecated . Por ejemplo, el error JDK-6481080 aclara que el intento de usar @Deprecated en un archivo @Deprecated no desaprueba el paquete; Este error fue arreglado la semana pasada. Y hay más trabajo por hacer, pero es algo especulativo en este punto.

El JDK está enfrentando problemas similares a los suyos, ya que tenemos que mantener las API en desuso para los clientes que todavía los están utilizando. Pero como usamos e implementamos dichas API internamente, tenemos muchas advertencias de desaprobación que eliminar. En el momento de redactar este documento, en nuestra línea de desarrollo JDK 9, aún no hemos podido compilar el sistema sin advertencias de desaprobación. Como resultado, las opciones de javac para advertencias de pelusas son todavía:

-Xlint:all,-deprecation

Es probable que también tenga que deshabilitar las advertencias de desaprobación en su compilación, especialmente si aún está utilizando JDK 6. No veo una forma de evitarlo en este momento.

Una nota final en uno de sus casos de desaprobación:

@Deprecated public class DeprecatedClass extends Bar<DeprecatedClass> { ... }

Esto no emite una advertencia de desaprobación, ni debería hacerlo. La Especificación del lenguaje Java, sección 9.6.4.6 , especifica que las advertencias de desaprobación no se emiten si el uso de una entidad desaprobada está dentro de una entidad que está en desuso.


Normalmente, cuando desapruebas la clase, no quieres que nadie la use en versiones posteriores. Además, TU base de código debe dejar de usar la clase obsoleta también. Parece extraño, cuando dices a todos que no utilicen la clase MySuperDeprecatedUtil sino que sigan usándola en su base de código.

Si necesita usar su clase MySuperDeprecatedUtil en alguna otra clase, debe marcar la clase donde la usa como @Deprecated: todas las clases que usaron código en desuso deben estar en desuso, o producirían advertencias de compilación, deberían eliminarse o deberían detenerse. utilizando código desaprobado.

Si no puedes dejar de usar tu clase, ¿quizás es demasiado pronto para desaprobarla?

En mi práctica, cuando quiero desaprobar alguna clase, creo una clase de reemplazo, por ejemplo, MySuperFreshUtil. Cambie todas las clases usando MySuperDeprecatedUtil a MySuperFresh para conservar las interfaces siempre que sea posible (si no es posible, use FQCN y marque el método como obsoleto). Marque MySuperDeprecatedUtil como @Deprecated y agregue un comentario sobre qué clase y cómo se debe usar en su lugar. Entonces me comprometo a hacer estos cambios en una sola lista de cambios.