为什么Java中的实例变量总是私有的?

为什么Java中的实例变量总是私有的?,java,instance-variables,Java,Instance Variables,我是Java新手,正在学习封装,并看到了一个实例变量在类中声明为私有的示例 我有两个问题: 为什么实例变量是私有的?为什么不公开 如果实例变量被公开并直接访问呢?我们是否看到任何限制 你能用一个例子解释一下,如果实例变量在Java类中声明为公共变量,会出现什么问题吗 因为如果更改类的结构(删除字段等);它会引起错误。但是如果您有一个getX()方法,您可以在那里计算所需的值(如果字段被删除) 你有一个问题,那就是类不知道是否有什么改变,不能保证完整性 首先,并非所有实例变量都是私有的。其中一些

我是Java新手,正在学习封装,并看到了一个实例变量在类中声明为私有的示例

我有两个问题:

  • 为什么实例变量是私有的?为什么不公开
  • 如果实例变量被公开并直接访问呢?我们是否看到任何限制

  • 你能用一个例子解释一下,如果实例变量在Java类中声明为公共变量,会出现什么问题吗

  • 因为如果更改类的结构(删除字段等);它会引起错误。但是如果您有一个
    getX()
    方法,您可以在那里计算所需的值(如果字段被删除)

  • 你有一个问题,那就是类不知道是否有什么改变,不能保证完整性


  • 首先,并非所有实例变量都是私有的。其中一些是受保护的,这仍然保留了封装

    封装的一般思想是类不应公开其内部状态。它应该只在执行其方法时使用它。原因是每个类都有一个所谓的“状态空间”。即,其字段的一组可能值。它可以控制其状态空间,但如果它将其公开,其他人可能会将其置于无效状态

    例如,如果您有两个布尔字段,并且该类只能在3种情况下正常工作:[false,false],[false,true]和[true,false]。如果将字段公开,则另一个对象可以设置[true,true],而不知道内部约束,并且对原始对象调用的下一个方法将触发意外结果

    将实例变量设置为公共或私有是一种设计权衡 设计器在声明类时会执行以下操作。举例说明 公共变量,公开类实现的详细信息, 从而提供更高的效率和简洁的表达 妨碍未来维护工作的可能费用。通过 隐藏类的内部实现的详细信息 将来更改类的实现的可能性 不破坏任何使用该类的代码


    它们不必是私人的,但它们应该是私人的。字段是一个实现细节,因此您应该将其保持为私有。如果您想允许用户获取或设置其值,可以使用属性(获取和设置方法)-这可以让您安全地执行(例如验证输入),还允许您更改实现细节(例如,将一些值委托给其他对象等)不丢失向后兼容性。

    实例变量被设置为私有,以强制这些类的用户使用方法访问它们。 在大多数情况下,有普通的getter和setter,但也可以使用其他方法

    例如,使用方法将允许您将访问限制为只读,即,如果没有setter,字段可能会被读取,但不会被写入。如果这一领域是公开的,那是不可能的

    此外,您可能会为字段访问添加一些检查或转换,这在对公共字段的普通访问中是不可能的。如果某个字段是公共的,并且您以后希望通过执行附加检查等的方法强制所有访问,那么您必须更改该字段的所有用法。如果将其设置为私有,则以后只需更改访问方法

    如果电话是私人电话:

    考虑这种情况:

    class Address {
      private String phone;
    
      public void setPhone(String phone) {
        this.phone = phone;
      }
    }
    
    //access:
    Address a = new Address();
    a.setPhone("001-555-12345");
    
    如果我们从这样的类开始,然后需要对电话号码执行检查(例如,一些最小长度、仅限数字等),您只需更改setter:

    class Address {
      private String phone;
    
      public void setPhone(String phone) {
        if( !isValid( phone) ) { //the checks are performed in the isValid(...) method
         throw new IllegalArgumentException("please set a valid phone number");
        }
    
        this.phone = phone;
      }
    }
    
    //access:
    Address a = new Address();
    a.setPhone("001-555-12345"); //access is the same
    
    如果电话是公用的:

    有人可以像这样设置
    手机
    ,而你对此无能为力:

    Address a = new Address();
    a.phone="001-555-12345";
    
    如果您现在想要强制执行验证检查,则必须将其设置为私有,并且编写上述行的人必须将第二行更改为:

    a.setPhone("001-555-12345");
    
    因此,您不能只添加检查而不破坏其他代码(它将不再编译)


    此外,如果您通过方法访问类的所有字段/属性,您可以保持访问一致,用户不必担心该属性是存储的(即是实例字段)还是计算的(只有方法而没有实例字段)。

    一些回答者已经指出,实例变量不必是
    私有的
    ,但为了保持封装,它们通常至少不被设置为
    公共的

    我在(我认为)干净的代码中看到了一个例子,很好地说明了这一点。如果我没记错的话,它是一个复数(如
    a+bi
    )类型;无论如何,像这样的东西,我手边没有这本书。它公开了获取实部和虚部值的方法以及设置实例值的方法。这样做的最大好处是,它允许在不破坏任何代码使用者的情况下完全替换实现。例如,复数可以存储在两种形式中的一种:作为复数平面上的坐标(
    a+bi
    ),或者以极坐标形式(
    φ
    |z
    )存储。将内部存储格式保留为一个实现细节允许您来回更改,同时仍然在两个窗体上公开数字,从而允许类的用户选择对他们当前执行的操作更方便的内容

    在其他情况下,可能会有一组相关字段,例如如果字段
    y
    在给定范围内,则字段
    x
    必须具有某些属性。一个简单的例子是,对于数值和一些任意值
    z