Java 没有封装的类
我在理解Java中的封装方面有点困难。我所知道的是,封装允许使用程序中任何其他地方的私有变量隐藏信息。但是,有谁能告诉我创建一个带有公共数据字段的类是如何导致问题的吗?如果类提供了getter和setter方法,我不理解数据是如何隐藏的Java 没有封装的类,java,encapsulation,Java,Encapsulation,我在理解Java中的封装方面有点困难。我所知道的是,封装允许使用程序中任何其他地方的私有变量隐藏信息。但是,有谁能告诉我创建一个带有公共数据字段的类是如何导致问题的吗?如果类提供了getter和setter方法,我不理解数据是如何隐藏的 public class Student{ private int id; private String name; private int grade; public Student(){ }
public class Student{
private int id;
private String name;
private int grade;
public Student(){
}
public Student(int id; String name, int grade){
this.id = id;
this.name = name;
this.grade = grade;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
//more code
}
下面是一个示例,其中公共字段可以使其类完全不可靠。另一种私有版本可以保证其信息始终有效,并且不受不受欢迎的参与者的影响 公共字段类不安全:
class VeryImportantCounterPublic {
public int currentCount;
public VeryImportantCounterPublic(int initial_count) {
currentCount = initial_count;
}
public void incrementCount() {
currentCount++;
}
public int getCurrentCount() {
return currentCount;
}
}
专用字段类安全:
class VeryImportantCounterPrivate {
private int currentCount;
public VeryImportantCounterPrivate(int initial_count) {
currentCount = initial_count;
}
public void incrementCount() {
currentCount++;
}
public int getCurrentCount() {
return currentCount;
}
}
主要内容:
输出:
[PUBLIC] Current count is -203847382
[PRIVATE] Current count is 6
完整资料来源:
public class CounterTest {
public static final void main(String[] ignored) {
VeryImportantCounterPublic counter = new VeryImportantCounterPublic(3);
counter.incrementCount();
counter.incrementCount();
counter.incrementCount();
counter.currentCount = -203847382;
System.out.println("[PUBLIC] Current count is " + counter.getCurrentCount());
VeryImportantCounterPrivate counter2 = new VeryImportantCounterPrivate(3);
counter2.incrementCount();
counter2.incrementCount();
counter2.incrementCount();
//Can't do this. Compiler error:
//counter2.currentCount = -203847382;
System.out.println("[PRIVATE] Current count is " + counter2.getCurrentCount());
}
}
class VeryImportantCounterPublic {
public int currentCount;
public VeryImportantCounterPublic(int initial_count) {
currentCount = initial_count;
}
public void incrementCount() {
currentCount++;
}
public int getCurrentCount() {
return currentCount;
}
}
class VeryImportantCounterPrivate {
private int currentCount;
public VeryImportantCounterPrivate(int initial_count) {
currentCount = initial_count;
}
public void incrementCount() {
currentCount++;
}
public int getCurrentCount() {
return currentCount;
}
}
getter和setter创建了一个更松散的耦合 比如说你雇了一个人帮你拿钱包 如果钱包的位置是公开的,那么您不知道您的员工在哪里损坏钱包。你可以直接抓住它,这样这个人就必须一直把它放在同一个口袋里
如果它的位置是私人的,你就不能再拿钱包了。您需要使用getter方法来请求它。考虑到你的合同雇员仍然必须把它交给你,他不必让你知道他到底把它放在哪里。因此,他可以开始把它放在任何他觉得舒服的地方——放在另一个口袋或包里——而不会违反合同。因此,您仍然可以在任何时候需要钱包,但您不必知道钱包被带到哪里。术语“信息隐藏”并不一定意味着信息的安全受到威胁。但是,在《代码完整版本2》一书中,史蒂夫·麦康奈尔写道: 公开成员数据违反了封装,限制了您对抽象的控制。 这里的关键洞察是,您失去了对使用您的代码的人之间的交互的控制,以及您打算如何操作代码。考虑给定示例代码的场景:您从您的老板/客户/老师那里得到了一个要求/约束,它说:对ID字段做一些错误检查,以确定它在一个范围内,可能只允许正数。您将如何实现该要求,以确保每当有人获得id时,它都遵循该要求 以下是该要求的示例实现:
public void setId(int id){
if(id < 0) {
this.id = 0;
} else {
this.id = id;
}
}
当有人坐在IDE前,甚至可能是你自己,继续实现代码时,他们怎么知道不使用上面设置id字段的方法?控制对该字段的访问的最佳方法是只允许一个入口点访问该字段。
也许“信息隐藏”最重要的方面是,如果您通过访问器和变异器控制对成员变量的访问,您可以在用户不知情的情况下进行实现更改。考虑一下这个场景:你的老板/客户/老师现在要求你将ID字段加密成一个字母数字字符串,而不影响用户已经使用你的软件版本1的代码。如果您允许直接访问成员变量,那么您永远无法更改id字段的内部表示形式,而不可能破坏人们可能已经在您上面编写的代码。他们可能正在执行以下操作:
Student student = new Student();
int currentId = student.id;
int idWithOffset = currentId + 100;
如果突然需要/想要将id设置为字符串或id对象,会发生什么情况?如果您将id保持为私有,则可以根据需要进行这些更改,并在setter/getter中编写处理转换逻辑的代码,用户的代码将永远不需要更改。
我个人最喜欢的最后一个原因是“信息隐藏”,例如使成员私有化,有助于减少问题,因为它删除了更多的代码细节,否则这些代码需要在UML图表、大脑、Javadocs等中浮动。。。信息隐藏有助于抽象,以便在处理该类时可以考虑该类中的所有组件和参与者,而不必在处理其他类时将其保留在大脑中。
干杯另外,在Java语言中,类似问题的一个很好的参考是Joshua Bloch第二版的《有效Java》。您的问题太广泛了,可能会被关闭。试想一下,如果所有人都可以使用你的钱包,那么你可能会面临什么样的问题?根据公众的定义,这是相似的。当你宣布任何事情公开的那一刻,它就成为你的班级合同的一部分,你必须永远维护它。我对整个编程非常陌生,我只是不明白在有getter和setter方法的情况下,私有化实例变量如何使它们不可访问@Lokesh@user3806226:花些时间阅读书籍/例子,你会有更好的理解。如果你问更精确的问题
人们将能够提供更好的帮助。因此,课程之间的唯一区别是从公共安全变为私人安全。当您编写这个counter.currentCount=-203847382时,您有能力仅仅因为您的变量是公共的就进行此更改吗@是的。将一个字段公开通常是一件坏事,尽管在某些不寻常的情况下这可能是合理的。这不仅是因为私有版本禁止您这样做,还因为您在编译过程中,而不是在编译后的运行时(根据定义)被告知这一点。您总是希望尽快了解错误,而将字段设置为私有字段是帮助您做到这一点的众多工具之一。编译错误总是比运行时错误好。非常感谢您的时间。这对我很有帮助,不客气。感谢大家的支持和接受。这就是他们提到封装时所说的黑箱操作的意思?你知道它在那里,但你不知道细节?@user3806226-对。但是最好说你不需要知道。除了安全方面,还有很多优点+1.
Student student = new Student();
student.id = -1;
Student student = new Student();
int currentId = student.id;
int idWithOffset = currentId + 100;