2015-06-28 32 views
6

Tôi đã luôn luôn được lập trình trong java, và gần đây tôi bắt đầu học một số c + +.Setter params cuối cùng trong Java

Trong C++, thông thường để đặt tham số setter là const, tại sao chúng ta không thấy điều này nhiều trong java?

tôi muốn nói là có bất kỳ khó khăn để tạo ra một setter như vậy:

public void setObject(final Object o){ this.o=o; } 

vs

public void setObject(Object o){ this.o=o; } 

Người đầu tiên sẽ thực hiện cho đối tượng param o ở lại liên tục thông qua toàn bộ chức năng thiết lập, không phải ?

Edit:

Một param cuối cùng sẽ thực thi này KHÔNG xảy ra:

public void setName(String name){ 
    name="Carlos"; 
    this.name=name; 
} 

Người dùng sẽ không bao giờ có thể thiết lập tên khác nhau từ "Carlos"

+2

Vì trong C++ bạn có thể gửi tham số như tham chiếu và con trỏ cho phép nhà phát triển thay đổi giá trị ban đầu, đôi khi do nhầm lẫn –

+1

Apropos: http://stackoverflow.com/questions/4162531/making-java-method-arguments-as-final – jdv

+0

Bởi vì Java là ** luôn luôn ** vượt qua bởi giá trị, sửa đổi các referene bên trong phương pháp được gọi là * về cơ bản * a no-op. Trong khi sửa đổi trạng thái thông qua tham chiếu sẽ hoạt động như trong C++. –

Trả lời

4

Được rồi, một final tham số/biến không thể được gán cho. Vì trình biên dịch java cần có khả năng xác định nếu một biến/tham số là thực sự là cuối cùng (đối với các lớp bên trong vô danh), tối ưu hóa không có yếu tố AFAIK.

Càng có nhiều C++ có bộ công cụ lớn hơn, mà java đã cố gắng giảm. Do đó, việc sử dụng C++ const string& là quan trọng, nói rằng

  1. Chuỗi được chuyển bởi con trỏ, quyền truy cập tự động được tham chiếu.
  2. Nếu đối số thực tế là một biến, chính biến đó sẽ không bị thay đổi.
  3. Tâm trí có thể có một toán tử chuyển đổi để chuyển một số khác không phải là const string&.

Bây giờ java:

  1. Java không phân bổ đối tượng trên stack, chỉ giữ các kiểu dữ liệu và đối tượng xử lý trên stack.
  2. Java không có thông số đầu ra: biến được chuyển đến cuộc gọi phương thức sẽ không bao giờ thay đổi giá trị tức thời của nó.

Về câu hỏi của bạn:

Là một setter trong java hầu hết sẽ không được hưởng lợi từ một tham số chính thức. Cuối cùng sẽ là hợp đồng không sử dụng biến cho nhiệm vụ thứ hai.

Tuy nhiên:

public final void setXyz(Xz xyz) { 
    this.xyz = xyz; 
} 

là hữu ích hơn: phương pháp này không thể được overriden, và do đó có thể được sử dụng một cách an toàn trong một constructor. (Gọi một phương thức overriden trong một hàm khởi tạo sẽ nằm trong bối cảnh của một thể hiện con không được khởi tạo.)

+0

Rất hay về chủ đề này, cảm ơn! 1+ –

6

Có chút lợi thế để đặt tham số phương thức Java là cuối cùng vì nó không ngăn ai đó thay đổi trạng thái tham chiếu tham số trong phương thức. Tất cả những gì nó ngăn cản là gán lại biến tham số cho một biến nào khác, nó không làm gì với tham chiếu ban đầu, và nó cho phép sử dụng tham số trong các lớp bên trong vô danh. Nếu bạn muốn an toàn thực sự trong tình huống này, bạn sẽ cố gắng làm cho các loại thông số của bạn trở nên bất biến nếu có thể.


Sửa
Bạn đã đăng:

public void setObject(Object o){ 
    o++; // this does not compile 
    this.o=o; 
} 

nào trộn nguyên thủy số và tài liệu tham khảo loại. Nó chỉ có ý nghĩa nếu o là một Integer hoặc lớp wrapper số khác, và ngay cả như vậy, làm cho nó cuối cùng sẽ không tránh người khác tạo:

private void setI(final Integer i) { 
    this.i = 1 + i; 
} 

Nhưng không phải mã của bạn cũng không mã này trên sẽ ảnh hưởng đến các đối tượng tham số trên phía mã gọi.


Sửa
OK bây giờ bạn đã đăng:

public void setName(String name){ 
    name="Carlos"; 
    this.name=name; 
} 

Nhưng rồi ai đó có thể viết

public void setName(final String name){ 
    this.name= name + " Carlos"; 
} 

Đây là nơi nguy hiểm đến và nơi cuối cùng không giúp . Giả sử bạn có một lớp được gọi là Tên:

public class Name { 
    private String lastName; 
    private String firstName; 
    public Name(String lastName, String firstName) { 
     this.lastName = lastName; 
     this.firstName = firstName; 
    } 
    public String getLastName() { 
     return lastName; 
    } 
    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 
    public String getFirstName() { 
     return firstName; 
    } 
    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 
} 

Và sau đó là một lớp, Foo, với trường Tên và trình cài đặt.Đây là nguy hiểm mã:

class Foo { 
    private Name name; 

    public void setName(final Name name) { 
     name.setFirstName("Carlos"); 
     this.name = name; 
    } 
} 

Bởi vì nó không chỉ thay đổi trạng thái của lĩnh vực này, nó thay đổi trạng thái của tài liệu tham khảo Tên trong mã gọi, và sửa đổi thức sẽ không giúp đỡ lẫn bit. Các giải pháp: làm cho Tên bất biến.

ví dụ

import java.util.Date; 

// class should be declared final 
public final class BetterName { 
    private String lastName; 
    private String firstName; 
    private Date dateOfBirth; 

    public BetterName(String lastName, String firstName, Date dob) { 
     this.lastName = lastName; 
     this.firstName = firstName; 

     // make and store a private copy of non-immutable reference types 
     dateOfBirth = new Date(dob.getTime()); 
    } 

    // only getters -- no setters 
    public String getLastName() { 
     return lastName; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public Date getDateOfBirth() { 
     // return copies of non-immutable fields 
     return new Date(dateOfBirth.getTime()); 
    } 
} 
+0

Có, nhưng điều này có nghĩa là nó sẽ là khôn ngoan để thiết lập params của bạn như là cuối cùng trong bạn setters phải (vì vậy bạn không bị mất giá trị ban đầu được đưa ra)? thì tại sao chúng ta không thấy điều này như một quy ước? –

+0

@KoenDemonie: Tôi không hiểu tuyên bố của bạn ở trên.Có thực tế không có lợi thế để thực hiện một tham số setter cuối cùng. Bạn có ý nghĩa gì bởi '" vì vậy bạn không bị mất giá trị ban đầu đã cho ""? Một lần nữa, điểm quan trọng nhất về nhà là cố gắng làm cho các lớp học của bạn bất biến khi nào và bất cứ nơi nào có thể. –

+0

Vâng, nếu nó không phải là cuối cùng một chức năng setter có thể thay đổi giá trị của nó, và mất giá trị ban đầu được đưa ra ... không có gì quá lớn nhưng thêm cuối cùng không làm tổn thương và có thể khắc phục vấn đề này –

Các vấn đề liên quan