2011-02-06 12 views
12

¿Hay una biblioteca existente de que me permite hacer anotaciones en un método Java como @Const, por lo que el compilador (usando apt supongo) marcará un error si se actualiza un campo, o no invoca un método @ Const en un campo ; y anotar un parámetro como @Const, para que el método de aceptación no pueda invocar ninguno de sus métodos que no sean @ Const ni actualizar ninguno de sus campos?Corrección de const en Java utilizando anotaciones?

(Básicamente, se trata de añadir const-corrección de Java utilizando anotaciones; hay algunos detalles obvios que no están cubiertos en la pregunta anterior, como asignar a/desde un parámetro de Const-mecanografiado @, etc.)

Encontré esto: http://confluence.atlassian.com/pages/viewpage.action?pageId=182158080 pero parece que solo está disponible como parte de IDEA.

Tras una solicitud de aclaración a continuación, aquí está el código de ejemplo para mostrar lo que quiero decir:

class Person { 
    private String name; 
    private String address; 

    @Const public String getName() { 
    return name; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 

    ... etc. for address 
} 

Ahora, si defino un método como:

void processPerson(@Const Person p) 

una línea como: p.getName() estaría bien en processPerson, ya que getName se marcó como un método @Const. Pero llamar a p.setName() desde dentro de processPerson se marcará como un error.

Tenga en cuenta que esto es muy diferente de final: si el parámetro se define como final Person p, cualquier asignación a p habría sido ilegal, pero sigue siendo perfectamente válido para modificar lo p se refiere a (ya sea usando p.setName(...) o incluso de forma más directa, con p.name = ....

+2

¿Intentó utilizar la palabra clave 'final' para este propósito? ¿Qué pasa con eso? – AlexR

+4

un método final es un método que no se puede anular. Eso es diferente. – aioobe

+0

Me refiero no al método final. Me refiero a la discusión final. Sé cuál es el método final :) – AlexR

Respuesta

8
  • JSR-305 supuestamente hace exactamente lo que estás buscando

  • Personalmente, me gustaría ver si puedo utilizar Hibernate Validator - Bean Validation (JSR-303) para eso. Es una pequeña lib maravillosa (no depende de la hibernación, es pequeña) y hace maravillas para mantener sus datos limpios. Vea el documentation.

  • Un hombre de google también comenzó Contracts for Java recientemente, pero puede que aún no sea la calidad de producción.

6

Tome un vistazo a la Checker Framework, que básicamente tiene las damas que tratan de detectar defectos de software [JSR-305] a través de un sistema de tipo de anotación extensible [JSR-308].

Tiene un comprobador de inmutabilidad (2 en realidad) que le permite anotar código con anotaciones de inmutabilidad como @Mutable, @Imutable y @Readonly. Esta herramienta diferencia entre una instancia inmutable y una referencia de solo lectura.

I amor este marco y principalmente lo uso para la comprobación nula, pero estoy tratando de comenzar a usar el verificador de inmutabilidad y el verificador de internamiento más.

anotar un parámetro como @Const, para que el método de aceptación no pueda invocar ninguno de sus métodos que no sean @ Const, o actualizar ninguno de sus campos?

se vería así:

void addFriend(@ReadOnly Friend friend) { this.friends.add(friend); } 

me permite hacer anotaciones en un método Java como @Const, por lo que el compilador (usando apt supongo) marcará un error si se actualiza un campo, o invoca un método que no es @ Const en un campo; y

se vería como esto para el ejemplo de la pregunta: ¿

public String getName(@ReadOnly Person this) { 
    return name; 
} 

El @ReadOnly aquí indica que el receptor (la instancia this cuyo método que se llama) debe NO ser modificados. A pesar de la aparente parámetro adicional, el método todavía se llama como de costumbre:

@ReadOnly Person person = new Person(); 
person.getName(); 

+1

¡Esto es perfecto, gracias! He estado buscando algo como esto por años, tan feliz de finalmente tenerlo con Java 8. Cosas muy poderosas, con un plugin de Eclipse y plugins de Maven, Ant, Gradle, etc. también, para cualquier otra persona interesada. Solo una recomendación es que las Anotaciones IGJ se ven mucho más expresivas que el verificador Javari para cualquier persona confundida por la superposición de características. Javari probablemente debería ser ignorado en mi humilde opinión. (También - respuesta editada para corregir la anotación del receptor en los métodos.) –

0

Estoy secundar comentario @AlexR, esto se puede hacer usando AspectJ, algo a lo largo de estas líneas:

public aspect ConstAspect{ 
declare warning : withincode(* *(..,@Const (*),..)) : "Calling Const Method.."; 
} 

Esto no es correcto para sus requisitos, pero básicamente quiero mostrar un enfoque. En el caso anterior, cualquier método que tenga un @Const en un parámetro está etiquetado con una advertencia. Con un mejor punto de unión, todos los puntos de preocupación se pueden etiquetar con un error.

-4

const estaba en C++. Java aparentemente lo abandonó a propósito. Y ahora las personas que crecen sin experiencia realmente const piensan que es una buena idea.

Una vez que marcó un método como const, se extenderá como cáncer, muy pronto se encontrará const casi todo. Hubiera sido mejor tener un not-const.

Totalmente es inútil. Es solo atractivo académicamente, no ayuda a nadie en el programa real.

+3

Es muy, muy discutible. Usé 'const' mucho en mis programas C++, y no recuerdo que se extendiera. Marcar getters como const y hacer const overloads de operadores de acceso (como 'operator []') realmente ayuda a prevenir modificaciones accidentales en los objetos. –

+4

Creo que const también es bueno (8 años de experiencia en C++). Y sobre la difusión: ¿qué hay de la especificación de excepción en un método? Se propaga como el cáncer, pero los desarrolladores de Java logran vivir con él. – mark

+8

Es una * buena * cosa que const se propaga 'como el cáncer'. Cuantas más cosas sean correctas, más seguro será el abuso de tu código. –

Cuestiones relacionadas