2008-09-16 26 views
51

Vì vậy, tôi đã cố tình giữ bản thân mình một Java n00b cho đến gần đây, và tiếp xúc thực sự đầu tiên của tôi mang lại một cú sốc nhỏ: Java không có thuộc tính phong cách C#!(không) Thuộc tính trong Java?

Ok, tôi có thể sống với điều đó. Tuy nhiên, tôi cũng có thể thề rằng tôi đã thấy mã getter/setter thuộc tính trong Java trong một codebase, nhưng tôi không thể nhớ ở đâu. Làm thế nào là đạt được? Có phần mở rộng ngôn ngữ cho điều đó không? Nó có liên quan đến NetBeans hay gì đó không?

Trả lời

59

Có mẫu "chuẩn" cho getters và setters trong Java, được gọi là Bean properties. Về cơ bản, bất kỳ phương thức nào bắt đầu bằng get, không lấy đối số và trả về một giá trị, là một thuộc tính getter cho một thuộc tính có tên là phần còn lại của tên phương thức (với một chữ cái bắt đầu thấp hơn). Tương tự như vậy set tạo ra một setter của một phương pháp void với một đối số duy nhất.

Ví dụ:

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

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

Hầu hết Java IDE sẽ tạo ra những phương pháp dành cho bạn nếu bạn hỏi họ (trong Eclipse nó đơn giản như di chuyển con trỏ đến một lĩnh vực và nhấn Ctrl-1, sau đó chọn tùy chọn từ danh sách).

Đối với những gì nó có giá trị, để có thể đọc bạn thực sự có thể sử dụng ishas ở vị trí của get cho thuộc tính boolean kiểu quá, như trong:

public boolean isAwesome(); 

public boolean hasAwesomeStuff(); 
+0

Tôi có thể thề tôi đã thấy cú pháp thuộc tính phong cách C# ở đâu đó trong một số mã Java, nhưng đối với cuộc sống của tôi Tôi không thể nhớ ở đâu và như thế nào. Điều này thực sự không trả lời câu hỏi của tôi nhưng tôi sẽ chấp nhận nó vì yếu tố tuyệt vời. Có lẽ tôi đã bị ảo giác rồi. – Ishmaeel

+0

Tôi khá chắc chắn rằng nó không thể được thực hiện trong Java, xin lỗi. Có rất nhiều ngôn ngữ JVM có hỗ trợ lớp học đầu tiên cho loại điều này, mặc dù, có lẽ đó là những gì bạn nhìn thấy? – Calum

+0

Có phải vi phạm quy ước này nếu bạn thêm tiền tố vào biến thành viên với một cái gì đó như 'm',' m_' hoặc '_', nhưng sau đó bạn không bao gồm tiền tố đó trong tên của thuộc tính? – Panzercrisis

2

Trải nghiệm Java của tôi cũng không cao, vì vậy bất kỳ ai cũng có thể tự do sửa tôi. Nhưng AFAIK, quy ước chung là viết hai phương pháp như vậy:

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

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

Nếu bạn đang sử dụng eclipse sau đó nó có khả năng để tự động tạo ra các phương thức getter và phương pháp setter cho các thuộc tính nội bộ, nó có thể là một hữu ích và công cụ tiết kiệm thời gian.

5

Quy ước đậu là để viết mã như thế này:

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

Trong một số ngôn ngữ khác trên JVM, ví dụ, Groovy, bạn sẽ có được tính overridable tương tự như C#, ví dụ:

int foo 

được truy cập với một đơn giản .foo và tận dụng các hoạt động mặc định getFoosetFoo mà bạn có thể ghi đè khi cần thiết.

3

Hầu hết các IDE cho Java sẽ tự động tạo getter và mã setter cho bạn nếu bạn muốn họ. Có một số quy ước khác nhau, và một IDE như Eclipse sẽ cho phép bạn chọn cái nào bạn muốn sử dụng, và thậm chí cho phép bạn tự định nghĩa nó.

Eclipse thậm chí còn bao gồm tái cấu trúc tự động cho phép bạn bao bọc thuộc tính trong trình lấy và đặt và nó sẽ sửa đổi tất cả mã truy cập trực tiếp thuộc tính, để làm cho nó sử dụng getter và/hoặc setter.

Tất nhiên, Eclipse chỉ có thể sửa đổi mã mà nó biết - bất kỳ phụ thuộc bên ngoài nào bạn có thể bị phá vỡ bởi việc tái cấu trúc như vậy.

1

Tôi vừa phát hành chú thích Java 5/6 và bộ xử lý chú thích để trợ giúp việc này.

Check-out http://code.google.com/p/javadude/wiki/Annotations

Các tài liệu là một ánh sáng chút ngay bây giờ, nhưng quickref sẽ nhận được các ý tưởng trên.

Về cơ bản, nó tạo ra một siêu lớp với getters/setters (và nhiều tùy chọn tạo mã khác).

Một lớp mẫu có thể trông như

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

Có rất nhiều mẫu hơn có sẵn, và không có phụ thuộc thời gian chạy trong mã được tạo.

Gửi cho tôi email nếu bạn dùng thử và thấy nó hữu ích! - Scott

6
public class Animal { 

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

Đây giống như thuộc tính C#. Đó là http://projectlombok.org/

+1

Điểm cần lưu ý: điều này sẽ được tính là phần mở rộng ngôn ngữ và có xu hướng khiến cho các IDE rất bối rối. – millimoose

+2

@millimoose Bạn chỉ cần một plugin cho IDE. Đáng buồn là tất cả mọi người sử dụng mã như vậy cần nó. – dantuch

+2

"Bạn cần một plugin cho IDE" làm cho tôi muốn cuộn lên một tờ báo và swat người chịu trách nhiệm về nó. (Mặc dù được cho là nhiều hơn trong trường hợp cấu hình IDE là hệ thống xây dựng chính cho một codebase.) – millimoose

29

Tôi ngạc nhiên là không ai đề cập project lombok

Vâng, hiện không có tài sản trong java. Có một số tính năng còn thiếu khác nữa.
Nhưng may mắn là chúng tôi có project lombok đang cố gắng cải thiện tình hình. Nó cũng ngày càng trở nên phổ biến mỗi ngày.

Vì vậy, nếu bạn đang sử dụng Lombok:

@Getter @Setter int awesomeInteger = 5; 

Mã này sẽ tạo getAwesomeIntegersetAwesomeInteger là tốt. Vì vậy, nó khá giống với C# auto-implemented properties.

Bạn có thể tìm thêm thông tin về getters lombok và setters here.
Bạn chắc chắn cũng nên xem other features. yêu thích của tôi là:

Lombok là cũng được tích hợp với IDE, do đó nó sẽ hiển thị các phương pháp tạo ra như thế nào nếu họ tồn tại (đề nghị, lớp nội dung, đi đến khai báo và tái cấu trúc).
Vấn đề duy nhất với lombok là các lập trình viên khác có thể không biết về nó. Bạn luôn có thể delombok mã nhưng đó là một giải pháp thay vì giải pháp.

+3

có các phương pháp mà bạn không thể thấy trong mã có vẻ còn tồi tệ hơn. Các thuộc tính tự động trong C# chỉ thực sự là một nửa câu chuyện - chủ yếu là về cách đặt tên và nhóm các logic liên quan. –

+6

@ JonnyLeeds tốt, nó tệ đến mức nào? Bạn có thể nhìn thấy chúng trong mã bằng cách phát hiện chú thích '' @ Getter'' và '' @ Setter'', và chúng cũng được hiển thị trong các thanh công cụ khác (như đường viền hoặc gợi ý) –

+0

Chú thích không được kế thừa - do đó ghi đè khả năng của bạn để phát triển hướng đối tượng. Nếu bạn đang làm OO, sau đó bạn biết rằng có rất ít lý do để thậm chí có getters và setters. Nó là tốt hơn nhiều để lộ hành vi hơn là mô hình dữ liệu. Chúng tôi cũng vượt ra ngoài nơi mọi người nên sử dụng cấu trúc (đậu). –

2

Từ Jeffrey Richter cuốn sách CLR thông qua C#: (Tôi nghĩ rằng những có thể là lý do tại sao bất động sản vẫn chưa được thêm vào trong JAVA)

  • Một phương pháp tài sản có thể ném một ngoại lệ; truy cập trường không bao giờ ném một ngoại lệ.
  • Không thể chuyển thuộc tính làm thông số out hoặc ref thành phương thức; một trường có thể.
  • Phương pháp thuộc tính có thể mất nhiều thời gian để thực thi; truy cập trường luôn hoàn thành ngay lập tức. Lý do phổ biến để sử dụng các thuộc tính là thực hiện đồng bộ hóa luồng, có thể dừng luồng vĩnh viễn và do đó, thuộc tính không được sử dụng được sử dụng nếu cần đồng bộ hóa luồng. Trong tình huống đó, một phương pháp được ưa thích. Ngoài ra, nếu lớp học của bạn có thể được truy cập từ xa (ví dụ, lớp học của bạn có nguồn gốc từ System.MarshalByRefObject), gọi phương thức thuộc tính sẽ rất chậm và do đó, phương pháp được ưu tiên hơn cho thuộc tính. Theo tôi, các lớp học có nguồn gốc từ MarshalByRefObject không bao giờ nên sử dụng các thuộc tính.
  • Nếu được gọi nhiều lần liên tiếp, phương pháp thuộc tính có thể trả về một giá trị khác nhau mỗi lần ; một trường trả về cùng một giá trị mỗi lần. Lớp System.DateTime có thuộc tính chỉ đọc Now trả về ngày giờ hiện tại. Mỗi lần bạn truy vấn thuộc tính này, nó sẽ trả về một giá trị khác. Đây là một sai lầm, và Microsoft mong muốn rằng họ có thể sửa chữa lớp bằng cách làm cho Bây giờ một phương pháp thay vì một tài sản. Environment ’s TickCount thuộc tính là một ví dụ khác về sai lầm này.
  • Phương pháp thuộc tính có thể gây ra các tác dụng phụ có thể quan sát được; truy cập trường không bao giờ. Trong các từ khác , người dùng thuộc loại sẽ có thể đặt các thuộc tính khác nhau được xác định theo loại trong số bất kỳ thứ tự nào họ chọn mà không nhận thấy bất kỳ hành vi nào khác trong loại.
  • Phương pháp thuộc tính có thể yêu cầu bộ nhớ bổ sung hoặc trả lại tham chiếu đến một cái gì đó không thực sự là một phần của trạng thái của đối tượng, do đó sửa đổi đối tượng trả lại không có hiệu lực trên đối tượng gốc; truy vấn một trường luôn trả về một tham chiếu đến một đối tượng được đảm bảo là một phần của trạng thái của đối tượng gốc. Làm việc với một thuộc tính trả về một bản sao có thể rất khó hiểu đối với các nhà phát triển và đặc điểm này thường là không được ghi lại.
+2

"" Đây là một sai lầm, và Microsoft mong muốn rằng họ có thể sửa chữa lớp bằng cách làm cho Bây giờ một phương pháp thay vì một tài sản "" Có bất kỳ bằng chứng về điều đó bất cứ nơi nào? Hãy thử thay thế tất cả các từ "thuộc tính" bằng "phương thức getter và setter" và đọc lại. Các văn bản nên được chính xác vẫn còn và là lý do tại sao tôi tìm thấy những loại lập luận ngớ ngẩn. Theo tôi, đây chỉ là "Tôi không hiểu bất động sản là gì, vì vậy tôi không thích nó" ... Vâng một tài sản chỉ là cú pháp thân thiện cho các phương thức getter và setter ... Vì vậy, nếu bạn không như tài sản, sau đó bạn shouln't như getter và setters hoặc là ... – Jens

3

Bạn có thể không cần cho "nhận được" và "thiết lập" tiền tố, để làm cho nó trông giống như thuộc tính, bạn có thể làm điều đó như thế này:

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()); 
    } 
} 
1

Không có từ khóa bất động sản trong java (như bạn có thể tìm thấy nó trong C#) cách gần nhất để có 1 từ getter/setter là làm như trong 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 
Các vấn đề liên quan