2012-09-07 27 views
21

Si tengo una clase de cliente con un constructor sobrecargado (predeterminado y uno con params) ¿cuál es la manera correcta de establecer los miembros de la clase en el constructor sobrecargado? ¿Usando "esto" referencias o usando los métodos setter?Mejor práctica de clase

Simplemente no estaba seguro de cuál era el método correcto.

public class Customer { 

private String firstName; 
private String lastName; 
private int age; 

public Customer() {} 

//This Way 
public Customer(String firstName, String lastName, int age) 
{ 
    this.firstName = firstName; 
    this.lastName = lastName; 
    this.age = age; 
} 

// Or this way? 
    public Customer(String firstName, String lastName, int age) 
{ 
    setFirstName(firstName); 
    setLastName(lastName); 
    setAge(age); 
} 



/** 
* @return the firstName 
*/ 
public String getFirstName() { 
    return firstName; 
} 

/** 
* @param firstName the firstName to set 
*/ 
public void setFirstName(String firstName) { 
    this.firstName = firstName; 
} 

/** 
* @return the lastName 
*/ 
public String getLastName() { 
    return lastName; 
} 

/** 
* @param lastName the lastName to set 
*/ 
public void setLastName(String lastName) { 
    this.lastName = lastName; 
} 

/** 
* @return the age 
*/ 
public int getAge() { 
    return age; 
} 

/** 
* @param age the age to set 
*/ 
public void setAge(int age) { 
    this.age = age; 
} 

}

Respuesta

27

El primero (usando this.) es probablemente más seguro y directo. Considere si una subclase futura anula los métodos del colocador; esto podría causar un comportamiento muy inesperado.

Si su clase es definitiva, esto es irrelevante y es un lavado.

+4

Esta es la única respuesta sensata hasta el momento. Varias herramientas de pelusa, de hecho, advierten acerca de llamar métodos no finales de los constructores debido a exactamente este problema. (Si la clase no es definitiva, pero sí lo son los métodos setter, es igual de buena). –

+0

@KumarVivekMitra - No me gusta su respuesta, como indica mi comentario al respecto. –

+0

@TedHopp por favor, lea mi respuesta de nuevo ... creo que los dos estamos hablando de la misma cosa ... todavía déjenme escribir de nuevo aquí ... Creo que están tomando el principio de 'OCP', Las clases están abiertas para extensión, pero están cerradas para modificación ... Y como sé 'Constructores no se pueden heredar, por lo que NO PUEDEN anularse, por lo que es inmutable ....' –

0

Básicamente, no hay ninguna diferencia, excepto para su validación.

Por un lado, si su setter valida nuevos valores basados ​​solo en los nuevos valores (no dependen del estado del objeto), llamar al setter evita duplicar la lógica de validación.

Por otro lado, si la validación de un setter comprueba otras propiedades, entonces usted debe asegurarse de que las propiedades necesarias ya están establecidas antes de llamar a ese setter, o asignar la propiedad directamente.

0

El acceso directo es más rápido (7 veces más rápido si la memoria me sirve correctamente) pero el segundo es "más seguro" en caso de algunas reglas especiales para asignar esos valores o encadenamiento de asignación (donde asigna un segundo campo del setter de otro) cuando se implemente en los accessors, a menos que, por supuesto, quiera explicitar las reglas/chainings cuando la asignación se hace desde el constructor.

En resumen, depende de sus necesidades, pero esas son las principales preocupaciones que se me ocurren.

+0

El segundo método está lejos de ser "más seguro" a menos que los métodos setter (o la clase) sean 'finales'. ¿Qué sucede si una subclase anula al colocador y no puede llamar a la superclase? –

+1

Si está subclasificando un tipo y está anulando los métodos setter sin configurar nada con ellos, entonces tiene un problema mucho mayor que decidir qué constructor utilizar. –

+0

@TedHopp Estaba escribiendo una descripción larga de lo que dijo Jordan White, así que lo dejo en eso :) – JTMon

1

La mejor respuesta sería "depende". En general, no es necesario utilizar setters a menos que los setters hagan algo más como un cálculo antes de establecer el valor. Sin embargo, si sus ajustadores solo establecen el valor directamente, entonces this es probablemente lo mejor para usted. Por el contrario, los setters se usan para la validación y esas cosas, si usas this, las perderás.

2

No se trata de que es una mejor manera de hacerlo, pero lo que quiere salir de ella ......

- Si desea que su clase sea mutable, y luego ir con setters.

- Si desea que su clase sea Immutable entonces creo que el uso de this, es una mejor opción.

Creo que usando this, es apto en lugares, donde recibe algunos datos de un servidor web o alguna fuente, luego los almacena en una Colección en forma de instancias de una clase personalizada .....

Ej:

  • Crear una clase Student,

  • Al hacer una petición a algún servicio web, obtendrá la respuesta, por ejemplo :JSON ..

  • Analizar, crear una instancia de estudiante y almacenarla en una colección.

    por ejemplo:

    ArrayList<Student> arList = new ArrayList<Student>();

    arList.add(new Student(name,rollNos,class,marks));

+0

Llamar a un método no final (como un setter) desde un constructor no es una buena idea. Consulte, por ejemplo, [este artículo] (http://www.informit.com/articles/article.aspx?p=20521). –

+0

@TedHopp Creo que está tomando el principio de 'OCP', las clases están abiertas para la extensión, pero están cerradas por modificación ... Y como sé' Los constructores no se pueden heredar, por lo que NO PUEDEN anularse, por lo que es inmutable. ... ' –

+0

Vea [esto] (https://www.securecoding.cert.org/confluence/display/java/MET05-J.+Ensure+that+constructors+do+not+call+superable+methods) para una buena explicación de por qué uno nunca debería llamar a un método invaluable de un constructor. La mayoría de las herramientas de pelusa se quejarán de llamar a los métodos setter desde un constructor (a menos que el método o la clase sea final, o el método sea privado, en cuyo caso el método no puede ser anulado). –

0

Como ya se dijo que es muy peligroso para llamar a métodos reemplazables en el constructor. Sin embargo, si necesita realizar algún tipo de validación que tenga lugar en el colocador, todavía tiene algunas formas sensatas de lograrlo.

  1. Haga que el colocador final. La solución más rápida. Este ya ha sido mencionado, pero no es la única opción.
  2. Utilice copia privada del setter.
  3. Use método de fábrica en lugar de constructor. Usualmente me quedo con este. Porque de esta manera usted tiene más libertad para manejar la situación si la validación falla y comunica el intento mejor que (2)