25

这是基本问题,但我仍然不了解封装概念。我不明白如何从其他类更改类的属性。因为每当我们尝试设置类的公共实例值时,我们必须创建该类的对象然后设置值。每个对象都引用不同的内存.so 即使我们更改实例值,这也不会影响任何其他对象。

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

下面给出示例

// 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

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

4

12 回答 12

40

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

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

封装是四个基本 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;
   }
}

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

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

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

关于它们的方式和内容有很多教程和解释。谷歌他们。

至于您当前的问题:

  1. 你有两个不同的类,每个类都有一个主类。那是错的。它们将具有不同的属性。
  2. @Subhrajyoti Majumder 建议的代码更改是正确的。检查答案以解决问题。

与此同时,请继续阅读

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

于 2013-09-27T07:07:27.620 回答
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);
    }

}
于 2013-09-27T06:52:39.077 回答
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);
      }
}

用于更好地理解封装的文档

于 2013-09-27T06:50:27.517 回答
2

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

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");
                }
}
于 2016-09-12T12:53:23.417 回答
1

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

于 2014-11-20T11:25:07.403 回答
1

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

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

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

根据您的要求进行编辑:

例子:

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

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

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

假设,您不想让外部世界改变您的对象名称属性。那么您应该将名称'name'设为私有,并提供一个仅查看名称(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";

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

于 2013-09-27T06:59:55.390 回答
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;
}
于 2014-05-28T14:28:09.803 回答
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;
  }
}

请注意,通过将属性声明为私有,此类限制客户端直接访问员工对象实例的状态。客户端访问它们的唯一方法是通过 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;
  }
}

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

于 2013-09-27T07:12:20.227 回答
0

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

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

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

于 2013-09-27T06:54:40.363 回答
0

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

1)变量的内存是在运行时分配的,并且在程序终止后也被释放。

2)因此,如果您认为一旦给 empid 10 它应该始终为 10,那么事实并非如此,因为 empid 只是对存储“10”的内存的引用。

3)所以通过释放,我的意思是 empid 不再指向存储 10 的内存区域,在程序终止后

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

于 2017-06-13T09:36:52.930 回答
0

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

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

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

于 2017-04-18T19:10:40.007 回答
0

封装是一个面向对象的概念。该类被认为是一个包含数据+行为的胶囊。数据应该是私有的,并且只能使用称为 getter 和 setter 的公共方法访问。您可以查看此封装教程以获取有关此概念的更多信息。

于 2016-08-22T13:15:06.963 回答