Java是否有类似于C#属性的东西?

100

C#属性(指get和set方法)是非常有用的特性。Java是否有类似于C#属性的功能?也就是说,我们如何在java中实现以下类似C#代码的功能:

public string Name
{
    get
    {
        return name;
    }

    set
    {
        name = value;
    }
}

2
请参阅Java中的getter/setter:https://dev59.com/questions/-nNA5IYBdhLWcg3wrPuq - Matthew Flaschen
另外,还可以查看CodePorting C#2Java Cloud-App http://codeporting.com/blog/csharp-to-java-conversion/archive/2012/05/09/migrating-c-properties-to-java-using-codeporting-c2java.html,该应用程序可以在将C#代码移植到Java时自动将C#属性转换为Java。 - user1345113
实际上,您可以省略 get 和 set 前缀,例如使用 public String name() {...} 作为 getter,public void name(String val) {...} 作为 setter。 “set” 和“get”是传统的命名方式,但很明显当你写下 name("Lem") 时正在设置值,获取值则是像 String n = name()。 - LEMUEL ADANE
@Scott,这不是OP所问的。类似的功能(非常相似)已经在Java 5发布后不久由Lombok提供了。 - Jayadevan Vijayan
传统的Java不支持,但Groovy支持它。由于它们是兼容的,几乎所有的Java都是有效的Groovy,如果您需要Java中的属性,那么这是一种方法。 - Jayadevan Vijayan
5个回答

117

不,Java没有等价物。它只有访问器和变异器方法,也就是getter和setter方法的花式命名。例如:

public class User {
    private String name;

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

80
应该明确,这些getter/setter方法并不像C#中的属性一样拥有花哨的语法作为单独的构造。相反,它们只是普通的方法,我们恰巧将它们命名为getName()和setName(),并通过惯例让它们扮演属性的角色,而不是通过专用的语言构造来实现。 - filip-fku
3
确实,getName()和setName()方法之所以被这样命名,纯粹是出于惯例。有人可以随意决定将这些方法命名为其他名称,例如retrieveUserName()和assignUserName(),也完全没有问题。这种约定在Java中很常见,像Eclipse IDE这样的工具也会遵循这种约定。 - Kevin Le - Khnle
26
这不仅仅是一个惯例。Java Beans 还附带有规范和 API,使其变得实用。http://java.sun.com/javase/technologies/desktop/javabeans/docs/spec.html - Chris Nava
5
@ChrisNava你的链接已经失效了。 - Ky -
值得注意的是,当我们谈论命名时: 在C#中,“属性是一种成员,它提供了一种灵活的机制来读取、写入或计算私有字段的值。” 在Java或JS中,这个术语有不同的含义。 - DanteTheSmith

31

你可以看一下Project Lombok,因为它试图简化编写样板Java代码的痛苦。它允许您使用@Getter@Setter注释,这将提供getBlah()setBlah()方法:

public class GetterSetterExample {
  @Getter @Setter private int age = 10;
}

或者你可以直接使用 @Data,它会自动实现你的hashCode()equals()toString()和getter方法以及非final字段的setter方法:

@Data public class DataExample {
  private String name;
}

然而,我发现该项目存在的问题是它有些神秘,可能会使人望而却步,并且你必须安装Eclipse(或其他)插件才能使自动编译工作。


16
另外一个问题是,如果您使用了Lombok,那么您就无法编写可移植的Java代码。 - Neal Gafter
1
你能解释一下这里的“可移植性”吗? - Lei Yang
@NealGafter 您说的Java代码不再可移植是什么意思? - smac89
1
我认为@NealGafter指的是Lombok必须得到您的编辑器和构建工具的支持,因此您的代码可能无法在所有开发平台/环境上运行。 - David Rochin
1
作为任何寻找C#行为的参考,这并不完全准确,您仍需要调用GetterSetterExample.getAge允许使用=设置属性的C# setters将在此处失败 GetterSetterExample.setAge = 10 无法使用Lombok语法实现 - Dataminion

17

属性不仅便于编写封装在单元中的gettersetter,而且它们在调用时提供了良好的语法。

Window.Title =  "New"; //which looks natural

getterssetters一起使用时,通常是这样的

Window.setTitle("New");

36
这样做甚至更糟,比如增量操作:C#: Thing.Number += 1Java: Thing.setNumber(Thing.getNumber() + 1) - Paul Etherton
14
这并没有回答问题,而只是描述了语法上的差异。 - Ky -
1
如果你只是在Java中使用公共字段,那么你就可以像在C#中一样做Window.Title = "New",而不需要属性。我从来没有完全理解它们在C#中的意义,但我仍然使用它们,因为它们很方便。 - Andy
3
@ozzy432836 以下是需要翻译的内容:这是情况...你可以将Window.Title =“New”分配给变量。但在C#中,你可以为其添加一个约束条件,告诉它如果Window.Title =“@some invalid value”则拒绝它。这就是我喜欢C#的美妙之处。希望Java世界也能理解!就像我们可以用汇编语言编写代码一样,为什么高级语言会演变出来呢?对我来说,我觉得Java世界在这方面很自大! - digitally_inspired

6

0
你可以声明一个私有变量,并手动编写方法。但是,如果你使用 Eclipse,你可以点击一个变量,选择“源”和“生成 getter 和 setter”。这与 C# 属性一样方便。

NetBeans也提供了自动方法生成的功能。 - Ky -
10
我不会说它和C#一样方便,因为我倾向于重命名属性,而不是仅更新一个属性的名称,所以我需要更新两个方法和一个变量。 - redsolo
4
C#属性不仅仅是“更加方便”,相较于标准的getter/setter,它们提供了更多的便利。 - Josh M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接