与Java Encapsulation Concept混淆

美好的一天!

我正在阅读一本关于封装的Java书,它提到了getter和setter方法。

我已经读过要隐藏属性,我必须将我的实例变量标记为“PRIVATE” ,并使用getter and setter“PUBLIC”方法来访问数据。 所以我尝试制作类似但不是传统的代码,如下所示:

 public class AddressBookEntry { private String name; private String address; private String telNo; private String email; public void getAllInfo() { name = JOptionPane.showInputDialog("Enter Name: "); address = JOptionPane.showInputDialog("Enter Address: "); telNo = JOptionPane.showInputDialog("Enter Tel. No: "); email = JOptionPane.showInputDialog("Enter Email Address: "); } } 

上面的代码是否暴露了我的变量,因为我直接分配了它? 我怎么能做得更好? 如果我改为使用传统的getter and setter方法并在其他类中分配值,会不会更好? “隐藏数据”是什么意思?

谢谢。

是的,不是。 封装的关键是它可以防止其他类需要知道你的类在幕后做了什么。 如果你将你的name存储在一个String (就像你在这里所做的那样),从一个文件中读取/写入它,或者做一些不同的事情,封装的重点在于你的类的用户无关紧要,因为它们都是 see是String getName( )void setName (String name)

由于数据的修改完全在您的类的控制之下,因此它不会破坏封装。 如果您确实name存储到文件中,那么您可以在getAllInfo执行此操作,而不getAllInfo任何其他用户更聪明。 由于来自类外部的可观察行为仍然隐藏了类的内部所做的事情,因此它仍然被封装。

也就是说,这是一种非常规的方法。 就像我在第一段中描述的那样,使用访问器方法(getter和setter)是一种更惯用的方法,对于使用您的代码的其他人来说更容易理解。 你可以做你做的事情,它不会破坏封装,但它不是我称之为优雅或典型的东西。

您可以使用setter和getter使变量可以从类外部访问。 在你的例子中,你将拥有

 public class AddressBookEntry { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } } 

您将从UI类访问name属性(在同一个类中混合UI和业务逻辑并不好):

 public class MyPane extends JFrame { public getAllData() { String name = JOptionPane.showInputDialog("Enter Name: "); AddressBookEntry entry = new AddressBookEntry(); entry.setName(name); // You can't use entry.name = name } } 

私有类成员(属性,字段)的想法是仅在声明类(而不是实例!)中直接访问它们。 所有其他类都必须使用其他访问器,例如getter和setter方法。 因此, AdressBookEntry存储名称,地址,telNo和电子邮件值的方式完全隐藏在类中。

您不必使用getter或setter,但有时候在课堂上也有充分的理由这样做。 如果在设置值之前进行某些日志记录或validation,则有时使用getter和setter是有意义的。

这不违反封装,因为它不会将内部数据暴露给另一个类。 您可能希望查看模型 – 视图 – 控制器 (MVC),以帮助将您的界面与数据分开。

传统的你根据需要为每个变量创建一个getter和setter,如下所示:

 public String getName() { return name; } public void setName(String name) { this.name = name; } 

不要为不需要在类外部访问的变量创建getter,也不要为不需要在类外部设置的变量创建setter。

如果遵循MVC并使用上面的传统getter和setter,你可以将视图代码放在别处并调用类似的东西

 myAddressBookEntry.setName(JOptionPane.showInputDialog("Enter Name: ")); 

我同意所提供的所有重要答案。 我想增加使用封装的另一个好处,就是通过隐藏客户端的数据 (就像上面描述的例子一样),你可以保证如何设置和获取这些实例变量,使你的类更容易维护和测试(即如果您有许多客户端操作对象变量,则不需要逐个类地编写新function,而只需修改getter和setter)。

通过仅使用对象setter和getter,可以从外部世界隐藏其实现的细节。 这是一个很好的优势,因此尝试与您的类​​交互的其他对象将无法破坏其function。 这也增加了系统有效实施的可能性。

我发现上面的答案已经回答了你的问题。 但是,我发现您的代码存在另一个问题,即安全性和数据完整性问题。 您将直接从用户的输入中填写您的类成员,无需对其进行任何validation。 例如,您可能想要检查电子邮件地址是否具有xyz@abc.com模式。 恶意用户还可能在输入中提供非常长的字符串,从而导致意外错误。

术语封装和信息隐藏可互换使用。 通过仅通过方法公开对象function,可以防止为您的私有变量分配任何不符合您要求的值。 创建封装良好的类的最佳方法之一是将其实例变量定义为私有变量,并允许使用公共方法访问这些变量。