56

所以,直到最近,我才任性地给自己留了一个Java n00b,而我第一次真正的曝光带来了一个小小的震惊:Java 没有C# 风格的属性!

好吧,我可以忍受。但是,我也可以发誓,我在一个代码库中看到了 Java 中的属性 getter/setter 代码,但我不记得在哪里。那是如何实现的?有语言扩展吗?它与NetBeans有关吗?

4

14 回答 14

64

Java 中有一个用于 getter 和 setter 的“标准”模式,称为Bean properties。基本上任何get以 . 同样set,使用单个参数创建 void 方法的设置器。

例如:

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

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

如果您提出要求,大多数 Java IDE 都会为您生成这些方法(在 Eclipse 中,只需将光标移动到某个字段并点击Ctrl- 1,然后从列表中选择选项)。

对于它的价值,为了可读性,您实际上也可以使用ishas代替get布尔类型的属性,如:

public boolean isAwesome();

public boolean hasAwesomeStuff();
于 2008-09-16T09:00:15.590 回答
34

我很惊讶没有人提到龙目岛项目

是的,目前java中没有属性。还有一些其他缺失的功能。
但幸运的是,我们有项目 lombok正在努力改善这种情况。它每天也越来越受欢迎。

因此,如果您使用的是 lombok:

@Getter @Setter int awesomeInteger = 5;

getAwesomeInteger这段代码也将生成setAwesomeInteger所以它与C# 自动实现的属性非常相似。

您可以在此处获取有关 lombok getter 和 setter 的更多信息。
您绝对应该检查其他功能。我最喜欢的是:

Lombok 与 IDE 完美集成,因此它将显示生成的方法,例如它们是否存在(建议、类内容、转到声明和重构)。
lombok 的唯一问题是其他程序员可能不知道它。您始终可以对代码进行delombok,但这与其说是解决方案,不如说是一种解决方法。

于 2013-08-28T19:47:01.413 回答
11

为 Java 7 提出了“Java 属性支持”,但没有将其纳入语言。

如果有兴趣,请参阅http://tech.puredanger.com/java7#property了解更多链接和信息。

于 2008-09-16T10:20:40.967 回答
6

bean约定是这样写代码:

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

在 JVM 上的其他一些语言中,例如 Groovy,您可以获得类似于 C# 的可覆盖属性,例如,

int foo

它可以通过简单的方式访问,.foo并利用您可以根据需要覆盖的默认值getFoosetFoo实现。

于 2008-09-16T08:59:58.477 回答
6
public class Animal {

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

这类似于 C# 属性。这是http://projectlombok.org/

于 2013-08-28T19:45:00.173 回答
4

你可能不需要“get”和“set”前缀,为了让它看起来更像属性,你可以这样做:

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());
    }
}
于 2015-01-28T02:37:12.743 回答
3

如果您愿意,大多数 Java IDE 会自动为您生成 getter 和 setter 代码。有许多不同的约定,像 Eclipse 这样的 IDE 将允许您选择要使用的约定,甚至可以让您定义自己的约定。

Eclipse 甚至包括自动重构,它允许您将属性包装在 getter 和 setter 中,并且它将修改直接访问该属性的所有代码,以使其使用 getter 和/或 setter。

当然,Eclipse 只能修改它知道的代码——您拥有的任何外部依赖项都可能被这种重构破坏。

于 2008-09-16T09:03:13.290 回答
2

我的 Java 经验也不是那么高,所以任何人都可以随时纠正我。但是 AFAIK,一般惯例是编写两种方法,如下所示:

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

public void setMyString(string myString) {
    // set it here
}
于 2008-09-16T08:58:21.803 回答
2

来自Jeffrey Richter 的CLR via C#:(我认为这些可能是 JAVA 中仍未添加属性的原因)

  • 属性方法可能会抛出异常;字段访问永远不会引发异常。
  • 属性不能作为outref参数传递给方法;一个字段可以。
  • 一个属性方法可能需要很长时间才能执行;现场访问总是立即完成。使用属性的一个常见原因是执行线程同步,这可以永远停止线程,因此,如果需要线程同步,则不应使用属性。在那种情况下,一种方法是优选的。另外,如果你的类可以远程访问(例如,你的类是从 派生的 System.MarshalByRefObject),调用属性方法会很慢,因此,方法比属性更受欢迎。在我看来,派生自的类不 MarshalByRefObject应该使用属性。
  • 如果连续多次调用,一个属性方法可能每次返回不同的值;一个字段每次返回相同的值。该类System.DateTime有一个只读 Now属性,它返回当前日期和时间。每次查询此属性时,它都会返回不同的值。这是一个错误,Microsoft 希望他们可以通过将 Now 设为方法而不是属性来修复该类。EnvironmentTickCount属性是这个错误的另一个例子。
  • 属性方法可能会导致可观察到的副作用;字段访问永远不会。换句话说,类型的用户应该能够以他或她选择的任何顺序设置类型定义的各种属性,而不会注意到类型中的任何不同行为。
  • 属性方法可能需要额外的内存或返回对实际上不属于对象状态的某些内容的引用,因此修改返回的对象对原始对象没有影响;查询一个字段总是返回一个对保证是原始对象状态的一部分的对象的引用。使用返回副本的属性可能会让开发人员感到非常困惑,而且这个特性通常没有记录。
于 2013-12-26T08:56:17.487 回答
1

如果您使用的是 eclipse,那么它可以自动为内部属性生成 getter 和 setter 方法,它可以是一个有用且省时的工具。

于 2008-09-16T08:59:24.843 回答
1

我只是发布 Java 5/6 注释和一个注释处理器来帮助解决这个问题。

查看http://code.google.com/p/javadude/wiki/Annotations

文档现在有点轻,但是 quickref 应该可以理解。

基本上,它使用 getter/setter(以及许多其他代码生成选项)生成一个超类。

示例类可能看起来像

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

还有更多可用的示例,并且生成的代码中没有运行时依赖项。

如果您尝试并发现它有用,请给我发送电子邮件!——斯科特

于 2008-09-16T14:21:17.080 回答
1

java 中没有属性关键字(就像你可以在 C# 中找到它一样),拥有 1 个单词 getter/setter 的最接近的方法是像在 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
于 2018-02-17T19:09:47.180 回答
0

正如前面提到的 Eclipse,集成开发环境 (IDE) 通常可以自动创建访问器方法。

您也可以使用 NetBeans 来完成。

要为您的类创建访问器方法,请打开一个类文件,然后右键单击源代码编辑器中的任意位置并选择菜单命令 Refactor、Encapsulate Fields。将打开一个对话框。单击全选,然后单击重构。瞧,

祝你好运,

于 2019-01-06T22:47:56.423 回答
0

对我来说,问题有两个方面:

  1. 所有这些额外的方法 {get*/set*} 使类代码混乱。
  2. 不能像对待属性一样对待它们:
    public class Test {
      private String _testField;

      public String testProperty {
       get {
        return _testField;
       }
       set {
        _testField = value;
       }
      }
    }

    public class TestUser {
      private Test test;

      public TestUser() {
        test = new Test();

        test.testProperty = "Just something to store";
        System.out.printLn(test.testProperty);
      }
    }

这是我想重新使用的那种简单的任务。不必使用“方法”调用语法。任何人都可以提供一些关于 Java 发生了什么的答案吗?

我认为问题还在于代码中不必要的混乱,而不是创建 setter/getter 的“困难”。我认为它们是丑陋的代码。我喜欢 C# 所拥有的。我不理解将这种功能添加到 Java 中的阻力。

我目前的解决方案是在不需要保护时使用“公共”成员:

public class IntReturn {
    public int val;
}

public class StringReturn {
    public String val;
}

这些将用于从 Lambda 中返回值:

StringReturn sRtn = new StringReturn()

if(add(2, 3, sRtn)){
    System.out.println("Value greater than zero");
}

public boolean add(final int a, final int b, final StringReturn sRtn){
    int rtn = a + b;
    sRtn.val = "" + rtn;
    return rtn > 0; // Just something to use the return for.
}

我也真的不喜欢使用方法调用来设置或获取类的内部值。

如果您的信息作为“不可变”传输,那么新的 Java记录可能是一个解决方案。但是,它仍然使用 setter/getter 方法,只是没有 set/get 前缀。

于 2019-11-28T11:12:18.357 回答