封装与普通

时间:2015-07-21 03:25:01

标签: java encapsulation

如果以下代码产生相同的结果,为什么要使用封装?

  

封装的主要好处是能够修改我们的   在不破坏使用我们代码的其他人的代码的情况下实现代码。

但我可以使用这个好处而不使用封装吗?因为每个对象的字段都彼此不同。

// Person.java
public class Person {
  // Plain
  public String name;

  // Uses encapsulation
  private String name2;
  public void setName(String name2) {
    this.name2 = name2;
  }
  public String getName() {
    return name2;
  }
}

// Main.java
public class Main() {
  public static void main(String[] args) {
    // Plain
    Person person = new Person();
    person.name = "Jordan";
    System.out.println(person.name);

    // Uses encapsulation
    Person person2=new Person();
    person2.setName("Jordan");
    System.out.println(person2.getName());
  }
}

4 个答案:

答案 0 :(得分:3)

  1. 通过提供getter和setter,我们可以获得隐藏实现的好处。例如您可以使用延迟初始化,代理等。
  2. 代码变得更易于维护,例如您可以在一个地方轻松添加前后检查(或验证)。如果您直接访问变量,稍后您需要在读取值时添加任何验证或某些默认行为,您必须在多个位置更改它。
  3. 通过getter和setter,您可以获得多态性的好处。例如如果您不希望在扩展版本中更改变量的值,反之亦然,您可以简单地抛出异常。

  4. 从调试的角度来看:

    1. 提供访问或更新变量值的代码行的隔离。 (可用于检查参考文献)
    2. 有时,我们需要知道变量值的变化位置。你可以把调试指针或记录器调查一下。

答案 1 :(得分:0)

封装是一种将类中的字段设为私有并通过公共方法提供对字段的访问的技术。

public class Person {

private String name;
private Date dob;
private transient Integer age;

public String getName() {
    return name;
}

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

public Date getDob() {
    return dob;
}

public void setDob(Date dob) {
    this.dob = dob;
}

public int getAge() {
    if (age == null) {
        Calendar dob_cal = Calendar.getInstance();
        dob_cal.setTime(dob);
        Calendar today = Calendar.getInstance();
        age = today.get(Calendar.YEAR) - dob_cal.get(Calendar.YEAR);
        if (today.get(Calendar.MONTH) < dob_cal.get(Calendar.MONTH)) {
            age--;
        } else if (today.get(Calendar.MONTH) == dob_cal.get(Calendar.MONTH)
                && today.get(Calendar.DAY_OF_MONTH) < dob_cal.get(Calendar.DAY_OF_MONTH)) {
            age--;
        }
    }
    return age;
  }
}

方法getAge()会告诉您年龄的人,您无需担心如何实施,也无需计算课外年龄。

答案 2 :(得分:0)

使用封装的一种方法是隐藏实现。例如,有时吸气剂不是吸气剂。考虑像球体这样的形状,我不会将体积或表面区域存储为变量,因为我可以随时计算它们。我仍然会调用成员函数getVolume和getSurfaceArea。使用我的代码的人不需要知道我是计算还是仅存储该值。通过公开我的变量,我将它们锁定在一个设计决策中,如果我改变我的实现,它将不得不改变(或被破坏)。通过隐藏实现,您只需要知道界面(不要与Java&#39;界面&#39;混淆)它以这种方式保护每个人并使未来的更改变得更容易。

应该注意的是,有时不使用setter / getter并暴露变量。即使在Java中,有时候也不会隐藏实例变量。

答案 3 :(得分:0)

你的问题非常有趣。我会尽力向你回答。

封装背后的主要思想是隐藏其他用户的数据及其实现详细信息。如果我们将数据成员私有,那么只能在同一个类中访问它。没有其他类可以直接访问该数据。

但是我们可以定义一个接口,即公共getter和setter方法来更新来自其他类的数据。这可以确保隐私数据仍然无法访问给其他人,并且只能通过您提供的公共方法进行访问。

例如,您可能决定只为特定数据成员提供getter方法,而不提供setter方法。这可确保其他任何类都无法以任何可能的方式更改或更新您的数据成员。如果他们想要使用getter方法,他们只能获得值。

这就是为什么封装也被称为数据隐藏

实施例

public class EncapsulationDemo{
    private int ssn;
    private String empName;
    private int empAge;

    //Getter and Setter methods
    public int getEmpSSN(){
        return ssn;
    }

    public String getEmpName(){
        return empName;
    }

    public int getEmpAge(){
        return empAge;
    }

    public void setEmpAge(int newValue){
        empAge = newValue;
    }

    public void setEmpName(String newValue){
        empName = newValue;
    }

    public void setEmpSSN(int newValue){
        ssn = newValue;
    }
}
public class EncapsTest{
    public static void main(String args[]){
         EncapsulationDemo obj = new EncapsulationDemo();
         obj.setEmpName("Mario");
         obj.setEmpAge(32);
         obj.setEmpSSN(112233);
         System.out.println("Employee Name: " + obj.getEmpName());
         System.out.println("Employee SSN: " + obj.getEmpSSN());
         System.out.println("Employee Age: " + obj.getEmpAge());
    } 
}

优点

1)它为代码提供了灵活性,并使其易于维护。我们可以更改getEmpName()setEmpName()的实施,而不会影响任何其他外部代码。

2)我们可以随时使数据成员只读(仅通过定义getter)或只写(仅通过定义setter)。

3)其他用户不知道幕后的内容。他们只知道要更新数据,我们需要调用清理器方法并获取调用getter方法所需的数据。