public class Foo {
public List<String> listaNombres;
public Foo() {
listaNombres = new ArrayList<>(Arrays.asList("Friky", "Luiggi"));
}
}
public class Otro {
public List<String> listaNombresOtro;
public void obtieneDeFoo(Foo foo) {
listaNombresOtro = foo.listaNombres;
}
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo.listaNombres);
Otro otro = new Otro();
otro.obtieneDeFoo(foo);
otro.listaNombresOtro.set(0, "Cambio");
System.out.println(foo.listaNombres);
System.out.println(otro.listaNombresOtro);
}
}
package paquete.de.mis.clases;
public class Foo {
private List<String> listaNombres;
public List<String> getListaNombres() {
return this.listaNombres;
}
//permite a Spring asignar el valor de la lista mediante reflexión
public void setListaNombres(List<String> listaNombres) {
this.listaNombres = listaNombres;
}
}
使用表达式语言进行字段关联的 JSF 示例:
<!-- permite a JSF llamar al getter mediante reflexión -->
<h:dataTable value="#{foo.listaNombres}" var="nombre">
<h:column>
#{nombre}
</h:column>
</h:dataTable>
相关的 Java 类:
package paquete.de.mis.managedbeans;
@ManagedBean
@ViewScoped
public class Foo {
private List<String> listaNombres;
@PostConstruct
public void init() {
listaNombres = new List<>();
listaNombres.add("Friky");
listaNombres.add("Luiggi");
}
public List<String> getListaNombres() {
return this.listaNombres;
}
public void setListaNombres(List<String> listaNombres) {
this.listaNombres = listaNombres;
}
}
此外,使用这些方法的“好处”(?)是您可以向它们添加业务逻辑以避免与您交互的对象直接接触。从前面的例子中我们指出我们想要获取列表的副本而不是直接获取列表,我们可以在 get 方法中添加这样的逻辑:
public class Foo {
private List<String> listaNombres;
public List<String> getListaNombres() {
//en lugar de devolver la lista directamente
//devolvemos una nueva lista con los elementos
//de mi lista actual
return new ArrayList<>(this.listaNombres);
}
}
public class Point {
int x = 0;
}
Point point = new Point();
point.x = 1;
相对
public class Point {
int x = 0;
public int getX() {
return this.x;
}
public void setX(int x) {
this.x = x;
}
}
Point point = new Point();
point.setX(1);
public void setNombre(String nombre) {
if (nombre!=null) throw new IllegalArgumentException("null no permitido");
this.nombre = nombre;
}
public void setApellido(String apellido) {
if (apellido!=null) throw new IllegalArgumentException("null no permitido");
this.apellido = apellido;
}
public class Persona {
private String nombre="";
private String apellido="";
private long timestamp=new Date().getTime();
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
if (!this.nombre.equals(nombre)) timestamp = new Date().getTime();
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
if (!this.nombre.equals(nombre)) timestamp = new Date().getTime();
this.apellido = apellido;
}
public Date getActualizado(){
return new Date(timestamp);
}
因此,可以仅在类中的模型中实现此功能。
相反,getter 和 setter 完全冗余的范式是不可变的VO(值对象,值对象)。一个例子:
public class PersonaVO{
public final String nombre;
public final String apellido;
public PersonaVO(String nombre, String apellido){
this.nombre=nombre;
this.apellido=apellido;
}
}
允许自由访问类属性并不是注定的设计,它只是不同而已。通常会避免这种情况,以便类在内部处理它可能附加到字段的任何业务逻辑。例如:
如果我们想在这段代码中添加验证,情况就复杂了。当然,在上面的例子中你看不到它,因为只有大约 3 次调用
Foo#listaNombres
,但如果它分散在几十个方法中,情况就会变得复杂。此外,如果属性的定义(名称、类型等)被更改,由于所有将要进行的更改,它也会变得复杂。另一个问题是,在获取列表时,Foo#listaNombres
我们不想直接传递列表,而是想要它的副本。我们可以在每个位置进行复制,foo.listaNombres
但这会导致重复代码(嗯,是成倍增加而不是重复)。get
和set
(最好是公共的)方法的使用符合JavaBean 规范:翻译:
这意味着 get 和 set 方法允许访问类的属性(属性)。许多框架都受益于这个定义。仅举几例:
使用 XML 配置从 Spring 中放置一个示例:
与此 bean 关联的 Java 类:
使用表达式语言进行字段关联的 JSF 示例:
相关的 Java 类:
此外,使用这些方法的“好处”(?)是您可以向它们添加业务逻辑以避免与您交互的对象直接接触。从前面的例子中我们指出我们想要获取列表的副本而不是直接获取列表,我们可以在 get 方法中添加这样的逻辑:
如果为这些方法生成代码似乎太费力,您可以使用lombok,它提供了通过代码中的注释添加这些方法的工具,以及其他好处。
改编自Private List with Getter/Setter vs Public List
您刚刚捕获了开发人员最常见的问题之一,“我是使用属性还是直接访问类属性?” 在其他答案中,您有很好的例子,我可以举一个简单的例子:
相对
第二段使用属性来控制属性的值,但是虽然它利用了面向对象编程的基本原则之一,但如果我们不要求(或将来会要求)就没有意义控制该属性的输入/输出。
你不需要应用你一开始就知道的所有理论概念,随着应用程序的成熟或扩展,控制需求的增加,你必须应用其中的许多概念,但是业务逻辑会告诉你是否应该封装您的应用程序的属性。类。有时过多的封装最终会创建代码怪物,例如:
当它可以更具可读性时:
但正如我之前所说,这将取决于您的应用程序的业务逻辑使用哪一个。
是的,有充分的理由使用它们,尽管它们不应该被认为是普遍必要的。如果您将变量(或字段)声明为 public,则您允许直接访问其内容而无需任何控制措施。在许多情况下,这不一定是问题,但随着系统的不断发展,它可能会成为问题。
实现访问变量的方法使您可以随时添加控制对变量的访问的代码,而无需更改类的接口。我给你一个例子。
让我们考虑这个类:
get
与带有and的版本相比set
在某些时候,我们意识到我们必须保证在任何时候都不会保留姓名或姓氏
null
。头等舱基本上是不可能
persona.nombre = null;
的,我们不能禁止。但是在另一个版本中,有一个超级简单的方法:如果有人试图设置 null,我们会得到一个异常。
一个更实际的例子是你必须实现一个时间戳来备份更新数据。如果没有 getter 和 setter,我们必须确保检查所有可以修改字段的代码。使用默认设置器的做法为我们提供了一条更简单的路径:
因此,可以仅在类中的模型中实现此功能。
相反,getter 和 setter 完全冗余的范式是不可变的VO(值对象,值对象)。一个例子:
在这种情况下,getter 或 setter 将完全没有意义。
如您所见,是的,有原因,但这完全取决于设计和上下文。
Gets 是类的输出,Sets 是类的输入。由于我们最大限度地封装,因此主要出于安全原因实施它们被认为是一种很好的做法。
我们隔离了数据的实际表示,并且只能访问行为。