关于getter setter :(否)Java中的属性?

关于getter setter :(否)Java中的属性?

(no) Properties in Java?

因此,直到最近我才故意保留Java n00b的身份,而我的第一次实际接触却引起了轻微的震惊:Java没有C#样式属性!

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


Java中有一个用于getter和setter的"标准"模式,称为Bean属性。基本上,任何以get开头,不带任何参数并返回值的方法都是该方法名称的其余部分(带有小写的起始字母)的属性获取器。同样,set创建带有单个参数的void方法的setter。

例如:

1
2
3
4
5
6
7
8
9
// 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的布尔类型属性,如下所示:

1
2
3
public boolean isAwesome();

public boolean hasAwesomeStuff();

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

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

因此,如果您使用的是龙目岛:

1
@Getter @Setter int awesomeInteger = 5;

该代码还将生成getAwesomeIntegersetAwesomeInteger。因此,它与C#自动实现的属性非常相似。

您可以在此处获取有关lombok吸气器和装夹器的更多信息。
您当然也应该检查其他功能。
我的最爱是:

  • NoArgsConstructor,RequiredArgsConstructor,AllArgsConstructor
  • 日志!

Lombok已与IDE很好地集成在一起,因此它将显示生成的方法,例如它们是否存在(建议,类内容,声明和重构)。
龙目岛的唯一问题是其他程序员可能对此一无所知。您总是可以delombok代码,但这只是解决方法,而不是解决方案。


为Java 7提出了" Java属性支持",但并未将其纳入语言。

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


1
2
3
4
5
6
public class Animal {

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

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


Bean约定是这样编写代码:

1
2
3
4
5
6
7
private int foo;
public int getFoo() {
    return foo;
}
public void setFoo(int newFoo) {
    foo = newFoo;
}

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

1
int foo

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


您可能不需要" get"和" set"前缀,以使其看起来更像属性,您可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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());
    }
}

杰弗里·里希特(Jeffrey Richter)通过C#编写的CLR :(我认为这可能是为什么仍未在JAVA中添加属性的原因)

  • 属性方法可能会引发异常。现场访问永远不会引发异常。
  • 属性不能作为outref参数传递给方法。田野可以。
  • 属性方法可能需要很长时间才能执行。现场访问始终完成
    立即。使用属性的常见原因是执行线程同步,
    可以永远停止线程,因此,属性不应为
    如果需要线程同步,则使用此选项。在这种情况下,首选方法。
    另外,如果您的班级可以远程访问(例如,您的班级派生自
    System.MarshalByRefObject),调用property方法将非常慢,并且
    因此,方法优于属性。我认为,从
    MarshalByRefObject永远不要使用属性。
  • 如果连续多次调用,则属性方法可能各自返回不同的值
    时间;字段每次都返回相同的值。 System.DateTime类具有只读
    返回当前日期和时间的Now属性。每次您查询此
    属性,它将返回不同的值。这是一个错误,Microsoft希望
    他们可以通过将Now作为方法而不是属性来修复该类。 Environment
    TickCount属性是此错误的另一个示例。
  • 属性方法可能会导致明显的副作用。现场访问从未如此。其他
    换句话说,类型的用户应该能够在其中设置由类型定义的各种属性
    他或她选择的任何顺序,而不会注意到类型中的任何不同行为。
  • 属性方法可能需要额外的内存或返回对某些内容的引用
    这实际上不是对象状态的一部分,因此修改返回的对象没有任何作用
    对原始物体的影响;查询字段始终返回对对象的引用
    保证是原始对象状态的一部分。与财产打交道
    返回副本可能会使开发人员非常困惑,而且此特征经常出现
    没有记录。

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

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

当然,Eclipse只能修改它知道的代码-这样的重构可能会破坏您拥有的任何外部依赖关系。


我的Java经验也不高,因此任何人都可以纠正我。但是AFAIK的一般约定是编写两个类似的方法:

1
2
3
4
5
6
7
public string getMyString() {
    // return it here
}

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

Java中没有property关键字(就像您可以在C#中找到它一样),拥有1个单词getter / setter的最接近方法是类似于C ++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

我只是发布Java 5/6注释和注释处理器来帮助实现这一点。

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

该文档现在有点轻巧,但是quickref应该可以理解这个想法。

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

示例类可能看起来像

1
2
3
4
5
6
@Bean(properties = {
    @Property(name="name", bound=true),
    @Property(name="age,type=int.class)
})
public class Person extends PersonGen {
}

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

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


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


对我来说,问题有两个:
1)所有这些额外的方法{get * / set *}使类代码杂乱无章。
2)无法像对待属性一样对待它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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发生了什么的答案?


如前所述,eclipse集成开发环境(IDE)通常可以自动创建访问器方法。

您也可以使用NetBeans做到这一点。

要为您的类创建访问器方法,请打开一个类文件,然后在源代码编辑器中的任意位置单击鼠标右键,然后选择菜单命令"重构","封装字段"。
将打开一个对话框。单击全选,然后单击重构。
Voilà,

祝好运,


推荐阅读