2008-09-16 12 views
51

Por lo tanto, me mantuve voluntariamente un Java n00b hasta hace poco, y mi primera exposición real provocó una pequeña conmoción: ¡Java no tiene propiedades de estilo C#!(no) ¿Propiedades en Java?

Ok, puedo vivir con eso. Sin embargo, también puedo jurar que he visto el código getter/setter de propiedades en Java en una base de código, pero no recuerdo dónde. ¿Cómo se logró eso? ¿Hay una extensión de idioma para eso? ¿Está relacionado con NetBeans o algo así?

Respuesta

59

Hay un patrón "estándar" para getters y setters en Java, llamado Bean properties. Básicamente, cualquier método que comience con get, no toma argumentos y devuelve un valor, es un captador de propiedades para una propiedad denominada como el resto del nombre del método (con una letra de inicio en minúscula). Del mismo modo, set crea un conjunto de un método vacío con un solo argumento.

Por ejemplo:

// Getter for "awesomeString" 
public String getAwesomeString() { 
    return awesomeString; 
} 

// Setter for "awesomeString" 
public void setAwesomeString(String awesomeString) { 
    this.awesomeString = awesomeString; 
} 

La mayoría de Java IDE generará estos métodos para que si les preguntas (en Eclipse es tan sencillo como mover el cursor a un campo y pulsando Ctrl-1, a continuación, seleccionando la opción de la lista).

Por lo que vale la pena, para facilitar la lectura en realidad se puede utilizar is y has en lugar de get para las propiedades de tipo booleano también, como en:

public boolean isAwesome(); 

public boolean hasAwesomeStuff(); 
+0

puedo jurar que he visto el C# hotel estilo de sintaxis en algún lugar de algún código de Java, pero para la vida de mí no puedo recordar dónde y cómo. Esto realmente no responde mi pregunta, pero la aceptaré por el factor asombroso. Quizás estuve alucinando en ese entonces. – Ishmaeel

+0

Estoy bastante seguro de que no se puede hacer en Java, lo siento. Hay muchos lenguajes JVM que tienen soporte de primera clase para este tipo de cosas, sin embargo, ¿tal vez eso es lo que viste? – Calum

+0

¿Es una violación de esta convención si prefija una variable miembro con algo como 'm',' m_', o '_', pero luego no incluye ese prefijo en el nombre de la propiedad? – Panzercrisis

2

Mi experiencia en Java tampoco es muy alta, por lo que cualquiera puede corregirme. Pero yo sepa, la convención general es escribir dos métodos de este modo:

public string getMyString() { 
    // return it here 
} 

public void setMyString(string myString) { 
    // set it here 
} 
1

Si utilizas Eclipse entonces tiene la capacidad para auto generar el captador y el método de selección de los atributos internos, puede ser una muy útil y herramienta para ahorrar tiempo.

5

La convención frijol es escribir código como este:

private int foo; 
public int getFoo() { 
    return foo; 
} 
public void setFoo(int newFoo) { 
    foo = newFoo; 
} 

En algunas de las otras lenguas en la JVM, por ejemplo, maravilloso, se obtiene propiedades reemplazables similares a C#, por ejemplo,

int foo 

al que se accede con un simple .foo y aprovecha las implementaciones predeterminadas getFoo y setFoo que puede anular según sea necesario.

3

La mayoría de los entornos de desarrollo para Java generará automáticamente captador y el código colocador para ti si quieres que lo hagan. Hay una serie de convenciones diferentes, y un IDE como Eclipse le permitirá elegir cuál desea usar e incluso le permitirá definir el suyo propio.

Eclipse incluye incluso la refactorización automatizada que le permitirá envolver una propiedad en un getter y un setter y modificará todo el código que accede a la propiedad directamente, para hacer que use el getter y/o setter.

Por supuesto, Eclipse solo puede modificar el código que conoce; cualquier dependencia externa que tenga se puede romper con dicha refactorización.

1

Acabo de lanzar anotaciones Java 5/6 y un procesador de anotaciones para ayudarlo.

Salida http://code.google.com/p/javadude/wiki/Annotations

La documentación es un poco de luz en este momento, pero el QuickRef debe transmitir la idea de.

Básicamente genera una superclase con los getters/setters (y muchas otras opciones de generación de código).

Una clase de ejemplo podría ser similar

@Bean(properties = { 
    @Property(name="name", bound=true), 
    @Property(name="age,type=int.class) 
}) 
public class Person extends PersonGen { 
} 

hay muchas más muestras disponibles, y no hay dependencias de tiempo de ejecución en el código generado.

Envíame un correo electrónico si lo pruebas y lo encuentras útil! - Scott

6
public class Animal { 

    @Getter @Setter private String name; 
    @Getter @Setter private String gender; 
    @Getter @Setter private String species; 
} 

Esto es algo así como las propiedades C#. Es http://projectlombok.org/

+1

Tenga en cuenta que esto se consideraría una extensión de lenguaje y tiende a confundir los IDE. – millimoose

+2

@millimoose Solo necesitas un complemento para IDE. Lamentablemente, todos los que usan dicho código lo necesitan. – dantuch

+2

"Necesita un complemento para el IDE" me da ganas de enrollar un periódico y golpear a la persona responsable. (Aunque podría decirse que eso es más en los casos en que la configuración IDE es el sistema de compilación primario para una base de código.) – millimoose

29

me sorprende que nadie mencionó project lombok

Sí, en la actualidad no hay ninguna propiedad en Java. También faltan algunas otras características.
Pero afortunadamente tenemos project lombok que está tratando de mejorar la situación. También se está volviendo más y más popular todos los días.

lo tanto, si usted está utilizando Lombok:

@Getter @Setter int awesomeInteger = 5; 

Este código se va a generar getAwesomeInteger y setAwesomeInteger también. Por lo tanto, es bastante similar a C# auto-implemented properties.

Puede obtener más información sobre lombok getters y setters here.
Definitivamente también debería consultar other features. Mis favoritos son:

Lombok está bien integrado con los entornos de desarrollo, por lo que se va a mostrar métodos generados como si existieran (sugerencias, clase contenidos, ir a declaración y refactorización).
El único problema con lombok es que otros programadores podrían no saberlo. Siempre puede delombok el código, pero eso es más bien una solución que una solución.

+3

tener métodos que no se pueden ver en el código parece incluso peor. Las auto-propiedades en C# son solo la mitad de la historia, se trata principalmente de nombrar y agrupar la lógica relacionada. –

+6

@JonnyLeeds bien, ¿cómo es malo en absoluto? Puedes verlos en el código detectando las anotaciones '' @ Getter'' y '' @ Setter'', y se muestran también en otras barras de herramientas (como el esquema o las sugerencias) –

+0

Las anotaciones no se heredan, lo que dificulta tu habilidad. hacer un desarrollo orientado a objetos Si estás haciendo OO, entonces sabes que hay muy pocas razones para incluso tener getters y setters. Es mucho mejor exponer el comportamiento que el modelo de datos. Estamos mucho más allá de donde alguien debería estar usando estructuras (frijoles). –

2

De libro CLR de Jeffrey Richter a través de C#: (creo que estos podrían ser las razones por las propiedades todavía no se agregan en Java)

  • Un método de propiedad puede producir una excepción; el acceso al campo nunca arroja una excepción.
  • No se puede pasar una propiedad como un parámetro out o ref a un método; un campo puede.
  • Un método de propiedad puede llevar mucho tiempo para ejecutarse; el acceso de campo siempre completa inmediatamente. Una razón común para usar propiedades es realizar la sincronización de subprocesos, , que puede detener el subproceso para siempre y, por lo tanto, una propiedad no debe ser si se requiere sincronización de subprocesos. En esa situación, se prefiere un método. Además, si se puede acceder remotamente a su clase (por ejemplo, su clase se deriva de System.MarshalByRefObject), llamar al método de propiedad será muy lento, y por lo tanto, se prefiere un método a una propiedad. En mi opinión, las clases derivadas de MarshalByRefObject nunca deben usar propiedades.
  • Si se llama varias veces seguidas, un método de propiedad puede devolver un valor diferente cada vez; un campo devuelve el mismo valor cada vez. La clase System.DateTime tiene una propiedad readonly Now que devuelve la fecha y la hora actuales. Cada vez que consulte esta propiedad , devolverá un valor diferente. Esto es un error, y Microsoft desea que puedan arreglar la clase haciendo Now un método en lugar de una propiedad. La propiedad Environment TickCount es otro ejemplo de este error.
  • Un método de propiedad puede causar efectos secundarios observables; el acceso al campo nunca lo hace. En otras palabras , un usuario de un tipo debe poder establecer varias propiedades definidas por un tipo en en cualquier orden que elija sin notar ningún comportamiento diferente en el tipo.
  • Un método de propiedad puede requerir memoria adicional o devolver una referencia a algo que no es realmente parte del estado del objeto, por lo que modificar el objeto devuelto no tiene efecto en el objeto original; consultar un campo siempre devuelve una referencia a un objeto que se garantiza que forma parte del estado del objeto original. Trabajar con una propiedad que devuelve una copia puede ser muy confusa para los desarrolladores, y esta característica con frecuencia es no documentada.
+2

"" Esto es un error, y Microsoft desea que puedan arreglar la clase al hacer de Now un método en lugar de una propiedad "" ¿Hay alguna evidencia de eso en alguna parte? Intente reemplazar todas las palabras "propiedad" por "métodos getter y setter" y vuelva a leer. El texto debe ser exacto aún y es por lo que me parece tonto este tipo de argumentos. En mi opinión, esto es solo "No entiendo qué es una Propiedad, por lo tanto, no me gusta" ... Bueno, una Propiedad es solo una sintaxis amigable para los métodos getter y setter ... Así que si no lo haces como propiedades, entonces tampoco te gustaría getter y setters ... – Jens

3

Puede que no necesite para "obtener" y "set" prefijos, para que se vea más como propiedades, puede hacerlo de esta manera:

public class Person { 
    private String firstName = ""; 
    private Integer age = 0; 

    public String firstName() { return firstName; } // getter 
    public void firstName(String val) { firstName = val; } // setter 

    public Integer age() { return age; } // getter 
    public void age(Integer val) { age = val; } //setter 

    public static void main(String[] args) { 
     Person p = new Person(); 

     //set 
     p.firstName("Lemuel"); 
     p.age(40); 

     //get 
     System.out.println(String.format("I'm %s, %d yearsold", 
      p.firstName(), 
      p.age()); 
    } 
} 
1

No hay palabra clave propiedad en Java (como se puede encontrar en C#) el camino más cercano para que 1 palabra captador/definidor es hacer como en C++:

public class MyClass 
{ 
    private int aMyAttribute; 
    public MyClass() 
    { 
     this.aMyAttribute = 0; 
    } 
    public void mMyAttribute(int pMyAttributeParameter) 
    { 
     this.aMyAttribute = pMyAttributeParameter; 
    } 
    public int mMyAttribute() 
    { 
     return this.aMyAttribute; 
    } 
} 
//usage : 
int vIndex = 1; 
MyClass vClass = new MyClass(); 
vClass.mMyAttribute(vIndex); 
vIndex = 0; 
vIndex = vClass.mMyAttribute(); 
// vIndex == 1 
Cuestiones relacionadas