Java Encapsulation Concept不清楚

时间:2013-09-27 06:47:36

标签: java encapsulation

这是基本问题,但我仍然不理解封装概念。我不明白我们怎样才能从其他类改变类的属性。因为无论什么时候 我们尝试设置类的公共实例值,我们必须创建该类的对象,然后设置值。每个对象引用不同的内存。即使我们改变 实例值,这不会影响任何其他对象。

即使我尝试使用静态公共实例值进行更改,我也无法更改类属性值。

示例如下:

// Employee class
public class Employee {
    public static int empid;
    public static String empname;

    public static void main(String[] args) {
        System.out.println("print employe details:"+empid+" "+empname);
    }

    // EmployeeTest  class
    public class EmployeeTest {

        public static void main(String[] args) {
            Employee e = new Employee();
            e.empid=20;
            e.empname="jerry";
            Employee.empid=10;
            Employee.empname="tom";
        }

    }
}

每次我运行Employee课程时,我都会获得相同的价值

print employe details:0 null

即使我没有遵循封装概念,也无法改变员工类的公共实例值。请帮助我理解我出错的概念。

12 个答案:

答案 0 :(得分:38)

是的,有时这可能有点令人困惑。让我们一步一步:首先,你需要了解

  • 什么是封装,为什么使用它。?

封装是四个基本OOP概念之一。封装是将类中的字段设为私有并通过公共方法提供对字段的访问的技术。如果一个字段被声明为私有,它不能被类外的任何人访问,从而隐藏了类中的字段。因此,封装也称为数据隐藏。

封装可以被描述为一种保护屏障,可以防止代码和数据被类外部定义的其他代码随机访问。通过接口严格控制对数据和代码的访问。

封装的主要好处是能够修改我们实现的代码,而不会破坏使用我们代码的其他人的代码。通过此功能,封装为我们的代码提供了可维护性,灵活性和可扩展性

举一个小例子:

public class EncapTest{

   private String name;
   private String idNum;
   private int age;

   public int getAge(){
      return age;
   }

   public String getName(){
      return name;
   }

   public String getIdNum(){
      return idNum;
   }

   public void setAge( int newAge){
      age = newAge;
   }

   public void setName(String newName){
      name = newName;
   }

   public void setIdNum( String newId){
      idNum = newId;
   }
}

上述方法称为Accessors(又名getter和setter)。现在你可能会问,

  • 为什么要使用访问者? 实际上有许多充分的理由考虑使用访问器而不是直接暴露类的字段.Getter和Setters使API更稳定。

例如,考虑一个类中的字段public,由其他类访问。现在稍后,您希望在获取和设置变量时添加任何额外的逻辑。这将影响使用API​​的现有客户端。因此,对此公共字段的任何更改都需要更改引用它的每个类。相反,使用访问器方法,可以轻松添加一些逻辑,如缓存一些数据,稍后懒洋洋地初始化它。此外,如果新值与先前值不同,则可以触发属性更改事件。所有这些都将与使用访问器方法获得价值的类无缝连接。

关于它们如何以及它们是什么,有很多教程和解释。谷歌他们。

至于你当前的问题:

  1. 你有两个不同的类,每个类都有一个main。那是错的。他们将拥有不同的属性。
  2. @Subhrajyoti Majumder建议的代码更改是正确的。检查解决问题的答案。
  3. 与此同时,请阅读

    以便更好地理解这些概念。希望能帮助到你。 :)

答案 1 :(得分:6)

您似乎分别运行两个不同的类,并假设在运行EmployeeTest时对属性所做的更改将反映在Employee运行中。请注意,更改将反映在同一JRE实例中。对不起,万一我误解了你的问题。

编辑:根据用户输入。下面是代码如何访问和更新静态成员值:

class Employee {
    public static int empid;
    public static String empname;

    public static void main(String[] args) {
        System.out.println("print employe details:" + empid + " " + empname);
    }
}

// EmployeeTest class
public class EmployeeTest {

    public static void main(String[] args) {
        Employee e = new Employee();
        e.empid = 20;
        e.empname = "jerry";
        Employee.empid = 10;
        Employee.empname = "tom";
        Employee.main(null);
    }

}

答案 2 :(得分:4)

public static字段与不与对象关联的类关联,它会破坏对象的封装规则。

带有两个封装字段Employee

empid & empname类。

public class Employee {
    private int empid;
    private String empname;

    public int getEmpid(){
        return this.empid;
    } 
    public void setEmpid(int empid){
        this.empid = empid;
    }
    ...
}

public class EmployeeTest {
      public static void main(String[] args) {
            Employee e = new Employee();
            e.setempId(1);
            Employee e1 = new Employee();
            e1.setempId(2);
      }
}

Documentation for better understanding on encapsulation

答案 3 :(得分:1)

当然,对一个对象的更改不会影响另一个对象。假设你有一个班学生,你学校的所有孩子都是它的对象。如果一个人离开学校,这并不意味着,每个其他学生(学生班的对象)也应该离开学校。

封装是将您的类变量设置为私有的概念,因此没有人可以直接使用来自外部世界的数据成员。但是你提供了公共方法,让外部世界以您希望的方式与您的数据成员一起玩。封面的好编码例子由Subhrajyoti Majumder给出。

(静态成员对于该类的所有对象都是相同的。例如:静态计数变量,用于计算学生班级对象的数量。(学校学生人数))。

根据您的要求进行编辑:

示例:

public class student{
    public String name;
    public student() {}
 }

在您的主要功能中,外部世界可以使用您的类属性:

student s = new student();
s.name = "xyz";

让我们假设,您不希望让外部世界更改对象的名称属性。那么你应该将名称'name'设为private,并提供一个公共方法来仅查看名称(get)。

示例:

public class student{
    private String name;
    public student() {}
    public String getName(){
      return this.name;
      }
 }

现在在main方法中,您只能获取名称对象,并且无法将其设置为新值,就像您在第一个示例中所做的那样。

student s = new student();
String sname = s.getName();

如果你尝试:

s.name = "newname";

编译器不会允许你这样做。因为您无权访问私人会员。

答案 4 :(得分:1)

封装的概念是一种与信息隐藏相关的设计技术。基本原则是通过精心设计的界面提供对类属性的受保护访问。封装的目的是强制实现类的不变量。

要继续您的示例,请考虑此类的接口:

class Employee

  private final String firstName;
  private final String lastName;    

  public Employee(final firstName, final lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public String getName() {
    return firstName + " " + lastName;
  }
}

请注意,通过将属性声明为private,此类限制客户端直接访问employee对象实例的状态。客户端访问它们的唯一方法是通过getName()方法。这意味着这些属性由类封装。还要注意,通过将属性声明为final并在构造函数中初始化它们,我们创建了一个有效的不可变类,即在构造之后无法修改其状态的类。

另一种实现方式如下:

class Employee

  private String firstName;
  private String lastName;    

  public Employee(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public String getName() {
    return firstName + " " + lastName;
  }

  public String setName(String firstName, String lastName) {

    if (firstName == null) {
      throw new IllegalArgumentException("First name cannot be null");
    }

    if (lastName == null) {
      throw new IllegalArgumentException("Last name cannot be null");
    }

    this.firstName = firstName;
    this.lastName = lastName;
  }
}

在此示例中,对象不是不可变的,但其状态是封装的,因为只有通过访问器和修饰符才能访问它。请注意封装如何帮助您保护对象状态的不变量。通过方法约束修改,您可以更好地控制对象状态的修改方式,添加验证以确保任何修改与类的规范一致。

答案 5 :(得分:1)

Encapsulation means combining data and code together(class). The main purpose of encapsulation is you would have full control on data by using the code.

class Encap{

private int amount;

public void setAmount(int amount)
{
this.amount = amount;
}

Here, you can set the amount using the setAmount method, but value should be more than 100. So, i have the control on it.

public void setAmount(int amount)
{
if(amount>100)
this.amount = amount;
}

答案 6 :(得分:1)

encapsulation = VARIABLES(让私人a,b,c)+ METHODS(setA& getA,setB& getB ....) 我们可以使用private修饰符进行封装。 让我们考虑一下你创建的一个公共变量和一个私有变量...... 如果你必须将这些变量提供给另一个只读类(只有它们可以看到并且无法修改),公共变量或方法是不可能的,但是我们可以通过提供get来私下做到这一点。方法。 所以你的类私有变量或方法在你的控制之下。但在公共场合没有机会....我想你可以理解。

答案 7 :(得分:1)

封装可以被描述为一个保护屏障,可以防止代码和数据被类外定义的其他代码随机访问。 通过界面严格控制对数据和代码的访问。

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

如果某个字段被声明为私有,则该类以外的任何人都无法访问该字段, 从而隐藏了班级中的字段。因此,封装也称为数据隐藏

实时示例:汽车和所有者。汽车的所有功能都由所有者封装。因此,没有其他人可以访问它..

以下是此示例的代码。

public class Main {

  public static void main(String[] args) {
    Owner o1=new Car("SONY","Google Maps");
    o1.activate_Sunroof();
    o1.getNavigationSystem();
    o1.getRadioSytem();
 }
}  
//Interface designed for exposing car functionalities that an owner can use.
public interface Owner {
     void getNavigationSystem();
     void getRadioSytem();
     void activate_Sunroof();
}
/*
Car class protects the code and data access from outside world access by implementing Owner interface(i.e, exposing Cars functionalities) and restricting data access via private access modifier.
*/
public class Car implements Owner {
                private String radioSystem;
                private String gps;

                public Car(String radioSystem, String gps) {
                    super();
                    this.radioSystem = radioSystem;
                    this.gps = gps;
                }

                public String getRadioSystem() {
                    return radioSystem;
                }

                public void setRadioSystem(String radioSystem) {
                    this.radioSystem = radioSystem;
                }

                public String getGps() {
                    return gps;
                }

                public void setGps(String gps) {
                    this.gps = gps;
                }

                @Override
                public void getNavigationSystem() {
                    System.out.println("GPS system " + getGps() + " is in use...");
                }

                @Override
                public void getRadioSytem() {
                    System.out.println("Radio system " + getRadioSystem() + " activated");
                }

                @Override
                public void activate_Sunroof() {
                    System.out.println("Sunroof activated");
                }
}

答案 8 :(得分:0)

运行Employee类时输出“print employees details:0 null”的原因是因为这些变量未初始化。也就是说,您不会在Employee类中为它们分配任何值。

无论您在EmployeeTest类中执行什么操作,都不会在下次运行时影响Employee中的变量值。将每个Java程序运行视为“干净的平板”。

关于封装,你真的不应该使用static关键字。如果您要进行封装,请查看此问题的其他答案,它有一个很好的代码示例供您使用。

答案 9 :(得分:0)

封装是OOP概念。 该类被视为包含数据+行为的包。 数据应该是私有的,只能使用名为getters和setter的公共方法访问。 您可以查看此encapsulation教程,了解有关此概念的更多信息。

答案 10 :(得分:0)

ENCAPSULATION是将方法和变量包装在一起作为一个单元的机制。例如胶囊,即混合了几种药物。

类的变量将从其他类中隐藏,因为它将被声明为私有,并且只能通过其当前类的方法访问

在Java中实现封装 - *将类的变量声明为私有。 *提供公共setter和getter方法来修改和查看变量值。 * Java Bean类是完全封装类的示例。

答案 11 :(得分:0)

你的意思是说empid的值应该是10而empname tom而不是0和null, 如果是,那么 - :

1)变量的内存在运行时分配,并在程序终止后解除分配。

2)因此,如果你认为如果你给10一个empid它应该总是10,那就不是这样,因为empid只是对存储“10”的存储器的引用。

3)因此,通过重新分配,我的意思是,在程序终止后,empid不再指向存储10的存储区

4)每当执行一个新程序时,empid现在指向其他内存区域,并且在静态变量的情况下,根据相应的数据类型为该内存分配默认值。 因此总是0和null。