在 Java 中,我覺得在宣告屬性時使用 Private 而不是為其宣告 Setter 方法與在宣告屬性時使用 Final 的結果相同,兩者都允許變數保持不變。
如果是這樣,在這種情況下使用 Final 有什么好處?
uj5u.com熱心網友回復:
即使沒有 setter,類中的其他方法也可以更改屬性,因此這是一個完全不同的概念。許多人會爭辯說這不是一件好事(它會給你的程式增加“副作用”),但它仍然是可能的。
uj5u.com熱心網友回復:
答案是Encapsulation
考慮一下。
public class Point
{
int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
//no getters or setters needed, I can just modify or read x and y directly.
}
public class FinalPoint
{
public final Point point;
public FinalPoint(int x, int y)
{
this.point = new Point(x, y);
}
//no getters needed, I'll just read point since it is public
}
現在,這FinalPoint有一個 finalPoint作為實體欄位。一方面,這意味著不能重新分配該實體欄位。但是,該實體欄位的欄位絕對可以重新分配。
例如。
FinalPoint p = new FinalPoint(1, 2);
p.point.x = 4; //I have now modified state! final did not protect us here
final關鍵字很強大,但并不代表你的資料一成不變。這僅意味著該表面級參考是不可更改的 - 它會強制參考始終指向同一個物件。這并不能阻止它指向的物件盡可能多地改變它的內部狀態。唯一的保證final是你總是指向同一個物件。
這將我們帶到了封裝。創建封裝是為了解決這個確切的問題等等。
考慮一下。
public class EncapsulatedPoint
{
private Point point;
public EncapsulatedPoint(int x, int y)
{
this.point = new Point(x, y);
}
public int getX() { return this.point.x; }
public int getY() { return this.point.y; }
}
現在,因為我只封裝Point和公開了我可以安全公開的資料,所以我保護自己不被修改。改變這個物件是不可能的(不使用反射或其他設計者正在積極洗掉的黑客)。它確實是不可變的。
當然,封裝并不優于使用final. 兩者都有時間和地點。知道何時何地可以讓您的軟體安全。
uj5u.com熱心網友回復:
私有變數永遠不會從類的外部訪問,并且 Final 永遠不會通過接受用戶的輸入而改變。
uj5u.com熱心網友回復:
假設你在談論變數、關鍵字final和private定義不同的特征。
關鍵字final拒絕對變數進行任何更改,并compilation errors在修改或更改時拋出。但是,如果不指定publicor private,則使用默認package-private訪問修飾符,它可以在初始化后被同一類中的其他類訪問package(帶有bold字體的文本由@charsofire和@MC Emperor更正)。
另一方面,關鍵字private拒絕被其他類呼叫的想法,即使在同一個包中也是如此。但它可以通過同一個類中的方法進行更改和修改,即使沒有setter或getter方法。
例如在相同class的相同package:
public class Student {
private int score;
final int id;
public Student(int id, int score) {
this.id = id;
this.score = score;
}
public void modifyGrade(int newScore) {
// Accepted
this.score = newScore;
}
public void modifyID(int id) {
// Rejected
this.id = id;
}
}
和不同class的相同package:
public class School {
public static void main(String[] args) {
Student student = new Student(0, 35);
// Accepted
System.out.println(student.id);
// Rejected
System.out.println(student.score);
// Accepted
student.modifyGrade(29);
// throws exception
student.id = 5;
// Not visible
student.score = 29;
}
}
希望這個回答對你有幫助
再次感謝@charsofire和@MC Emperor,他們在這個答案中做出了重要的澄清。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/476331.html
上一篇:使用Mutablelivedata從DialogFragmentColorPicker更改片段的背景顏色不起作用
