JetBrains’ @Contrato de anotación

¿Cómo funciona el org.jetbrains.annotations.Contract anotación de trabajo?
¿Cómo IntelliJ IDEA de apoyo?

3 Kommentare

  1. 45

    En primer lugar, debo decir que esta anotación es sólo para la IDEA a utilizar para comprobar los posibles errores. El compilador de Java se ignoran casi por completo (que va a ser en el compilado artefacto, pero no tienen ningún efecto). Habiendo dicho eso…

    El objetivo de la anotación es describir un contrato que el método va a obedecer, que ayuda a la IDEA de detectar problemas en los métodos que pueden llamar a este método. El contrato en cuestión es un conjunto de semi-separada por puntos y cláusulas, cada una de las cuales describe una entrada y una salida que está garantizado a suceder. La causa y el efecto están separados por ->, y describir el caso que al suministrar X para el método, Y se siempre resultado. La entrada es descrito como una lista separada por comas, describe el caso de múltiples entradas.

    Las entradas posibles son _ (cualquier valor), null, !null (no nulo), false y true, y las posibles salidas añade fail a esta lista.

    Así, por ejemplo, null -> false significa que, siempre que un null de entrada, un false booleano es el resultado. null -> false; !null -> true se expande en esto para decir que null se siempre volver false y nonull valor siempre devolver true, etc. Finalmente, null -> fail significa que el método producirá una excepción si se le pasa un valor nulo.

    Para múltiples argumento de ejemplo, null, !null -> fail significa que, en una de dos argumentos método, si el primer argumento es null y el segundo no es null, se producirá una excepción, garantizado.

    Si el método no cambia el estado del objeto, pero sólo devuelve un valor nuevo, entonces usted debe establecer pure a la verdad.

  2. 27

    La la documentación oficial especifica el la gramática formal de todas las ediciones y los valores reconocidos por la anotación.

    En los términos del laico:

    • Un contrato puede tener 1 o más cláusulas asociadas con ella
    • Una cláusula es siempre [args] -> [effect]
    • Args son de 1 o más de las restricciones, que se definen como any | null | !null | false | true
    • Efectos son sólo una restricción o fail

    Vamos a ejecutar a través de un ejemplo rápido – uno de mis favoritos es «todo Lo que pase en este método, se generará una excepción.»

    @Contract("_-> fail")
    public void alwaysBreak(Object o) {
        throw new IllegalArgumentException();
    }

    Aquí, estamos usando _, o «cualquier», para indicar que, independientemente de lo que pase en este método, vamos a lanzar una excepción.

    Lo que si nos mintió y dijo que este método se va a volver true incondicionalmente?

    @Contract("_-> true")
    public void alwaysBreak(Object o) {
        throw new IllegalArgumentException();
    }

    IntelliJ plantea algunas advertencias acerca de él.

    JetBrains' @Contrato de anotación

    También (obviamente) el malestar que dijimos que íbamos a devolver un booleano cuando estamos en un vacío método…

    JetBrains' @Contrato de anotación


    Los principales veces usted se encontrará a querer usar @Contract es cuando:

    • Desea garantizar que se devuelva true o false
    • Desea garantizar que devuelve un valor no nulo restricciones dadas
    • Que quiero dejar en claro que puede devolver un valor null restricciones dadas
    • Que quiero dejar en claro que va a lanzar una excepción restricciones dadas

    Eso no quiere decir que @Contract es perfecto; muy lejos de eso. No puede hacer análisis muy profundo en ciertos contextos, pero teniendo esto en su base de código permite a sus herramientas para hacer este tipo de análisis de forma gratuita.

  3. 18

    ¿Cómo funciona el org.jetbrains.annotations.Contract anotación de trabajo?

    Aunque las respuestas anteriores son de carácter informativo, no creo que la dirección de la palabra «trabajo» en su pregunta. Es decir, no explican lo que IntelliJ está haciendo detrás de las escenas para implementar sus anotaciones de modo que usted puede construir su propio fácilmente desde cero.

    Si usted vistazo al código fuente a continuación, usted podría pensar que se parece un poco demasiado complicado (o al menos detallado) para algo tan simple que suena como @NotNull. Yo estaría de acuerdo con usted, y es una de las razones por lo que generalmente evitar @Contract-como las cláusulas que no son «simple y sencillo» (como @NotNull) y en lugar de JavaDoc mi prereqs directamente.

    Me generalmente desalientan el uso de contratos complejos anotaciones—a pesar del odio que pudiera recibir la omisión de esta nueva moda de tren—y aquí algunas razones:

    • Anotaciones pueden ser complejas—por ejemplo, tener múltiples anidada anotaciones en sus propias definiciones y/o una «gramática» con la aparición de Turing integridad. Esto puede conducir a una falsa sensación de confianza en tiempo de compilación por enmascarar el verdadero culpable de un error detrás de capas de oscuridad/abstracción y no generar la originalmente la intención de advertencias.
    • Similar pero diferente de mi anterior punto, anotaciones a menudo se esconden abundante lógica del desarrollador en un puñado de palabras clave, produciendo difícil de entender para los humanos y/o comportamiento inusual que puede ser difícil de depurar.
    • Configuración de aplicación es a menudo visto el enmascaramiento de como anotaciones. Eche un vistazo a la Framework Spring.
    • La sintaxis para la definición de los contratos en general (en mi humilde opinión) bastante feo y Make-ish. Por ejemplo, echar un vistazo a algunos de los JetBrains anotación definiciones y archivos de soporte dispersos a través de su repo. Aviso a los numerosos archivos XML y abundante auto-referencia? Me gustaría apenas se llame que es divertido escribir y apoyo, especialmente teniendo en cuenta la naturaleza constantemente cambiante de las anotaciones encabezada por la parte de atrás y adelante entre Android y la más grande comunidad de Java.

    Algunas preguntas a considerar:

    • Es ir demasiado lejos cuando una anotación del código fuente de los enfoques de la complejidad de la misma fuente se anota?
    • Es el segmento de código debajo de verdad que mucho mejor que sólo la comprobación de null en tiempo de ejecución y el registro de excepciones con stacktraces? Incluso algo como que obliga a los usuarios a través de leer, comprender, y, posiblemente, de corrección de errores de otro conjunto de dependencias que definen sus anotaciones.

    Tomado de sin embargo, otro largo post sobre el contrato semántica que diría yo que sólo sirve a mi punto:

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import javax.annotation.Nonnull;
    import javax.annotation.meta.TypeQualifierDefault;
    
    /**
     * This annotation can be applied to a package, class or method to indicate that the class fields,
     * method return types and parameters in that element are not null by default unless there is: <ul>
     * <li>An explicit nullness annotation <li>The method overrides a method in a superclass (in which
     * case the annotation of the corresponding parameter in the superclass applies) <li> there is a
     * default parameter annotation applied to a more tightly nested element. </ul>
     * <p/>
     * @see https://stackoverflow.com/a/9256595/14731
     */
    @Documented
    @Nonnull
    @TypeQualifierDefault(
    {
        ElementType.ANNOTATION_TYPE,
        ElementType.CONSTRUCTOR,
        ElementType.FIELD,
        ElementType.LOCAL_VARIABLE,
        ElementType.METHOD,
        ElementType.PACKAGE,
        ElementType.PARAMETER,
        ElementType.TYPE
    })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NotNullByDefault
    {
    }

    Cuando y qué contratos se debe utilizar?

    Sugiero que se pegue a la clase cuyas intenciones son cristalinas de su nombre, y evitar aquellos con su propio conjunto de la semántica y el lenguaje-como definiciones.

    Un ejemplo de un uso de—a pesar de que en el segmento anterior—es @NotNull, pero mantenerlo limitado a, cuando todos los parámetros del objeto debe ser null.

    Un ejemplo de la clase para evitar son aquellos que, como Android y IntelliJ del @Contract(...). Mientras hago el amor de sus IDEs, los detalles de sus anotaciones son bastante complicadas, y en última instancia se convirtió en una fuente de más problemas y de la plataforma de incompatibilidad para mí de seguir (es cierto que causado por mi propia ignorancia en la creación de nuevos contratos de casi el 100% del tiempo, pero ¿por qué es tan difícil hacer lo correcto?)

    Resumen /Conclusión

    Las anotaciones son una gran idea claramente generado por los programadores que buscan «codificar» su documentación. Creo que he ido demasiado lejos últimamente, el giro de la documentación en la semántica de rodamiento código que conduce a serios interrogantes y situaciones incómodas. Peor aún, a veces se dote de un sentido falso de tiempo de compilación de seguridad al no detectar problemas de manifiesto en sus propias implementaciones. Se adhieren a la muy simple y evitar cualquier cosa que se parece a un idioma que no es Java (que es lo que pretende ser la escritura en el primer lugar).

    Leer Más

    Esta breve lista es una mezcla de la mayoría de críticos (w/optimismo!) procedente tanto de fuentes de StackOverflow y la web de la que me siento a ilustrar algunos de mis puntos.

    Sin ningún orden en particular:

    Y después de todo eso, me di cuenta de que puedo haber podido resolver tu pregunta original en su totalidad 🙂

    • Si bien esta es una que vale la pena tener esta discusión, este post también no responde a la pregunta acerca de cómo @Contract obras. No atiende a la pregunta que hace en absoluto, de hecho, a diferencia de las otras respuestas. Te sugiero que convertir este en un blog o algo.
    • Cierto, pero me hizo ya mención que…ver la última línea de mi post. También, mi punto es que la pregunta requiere una discusión más profunda y no tiene una respuesta simple.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea