Java 没有封装的类

Java 没有封装的类,java,encapsulation,Java,Encapsulation,我在理解Java中的封装方面有点困难。我所知道的是,封装允许使用程序中任何其他地方的私有变量隐藏信息。但是,有谁能告诉我创建一个带有公共数据字段的类是如何导致问题的吗?如果类提供了getter和setter方法,我不理解数据是如何隐藏的 public class Student{ private int id; private String name; private int grade; public Student(){ }

我在理解Java中的封装方面有点困难。我所知道的是,封装允许使用程序中任何其他地方的私有变量隐藏信息。但是,有谁能告诉我创建一个带有公共数据字段的类是如何导致问题的吗?如果类提供了getter和setter方法,我不理解数据是如何隐藏的

   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;