簡體   English   中英

Java Encapsulation Concept不清楚

[英]Java Encapsulation Concept not clear

這是基本問題,但我仍然不理解封裝概念。 我不明白如何從其他類更改類的屬性。因為每當我們嘗試設置類的公共實例值時,我們必須創建該類的對象然后設置值。每個對象引用不同的內存即使我們更改實例值,這也不會影響任何其他對象。

即使我嘗試使用靜態公共實例值進行更改,我也無法更改類屬性值。

實例如下

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

即使我沒有遵循封裝概念,我也無法改變員工類的公共實例值。請幫助我理解我出錯的概念。

是的,有時這可能有點令人困惑。 讓我們一步一步走:首先,你需要了解

  • 什么是封裝,為什么使用它?

封裝是四個基本OOP概念之一。封裝是一種將類中的字段設為私有並通過公共方法提供對字段的訪問的技術。 如果某個字段被聲明為私有,則該類之外的任何人都無法訪問該字段,從而將該字段隱藏在該類中。 因此,封裝也稱為數據隱藏。

封裝可以被描述為一種保護屏障, 可以防止代碼和數據被類外定義的其他代碼隨機訪問 對接口嚴格控制對數據和代碼的訪問。

封裝主要好處是能夠修改我們實現的代碼而不破壞使用我們代碼的其他人的代碼。 通過此功能, Encapsulation為我們的代碼提供了可維護性,靈活性和可擴展性

舉一個小例子:

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建議的代碼更改是正確的。 檢查解決問題的答案。

在此期間,請繼續閱讀

為了更好地理解這些概念。 希望能幫助到你。 :)

您似乎分別運行兩個不同的類,並假設在運行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);
    }

}

public static字段與不與對象關聯的類關聯,它打破了對象的封裝規則。

具有兩個封裝字段empid & empname Employee類。

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);
      }
}

有關更好地理解封裝的文檔

封裝可以被描述為一種保護屏障,可以防止代碼和數據被類外定義的其他代碼隨機訪問。 對接口嚴格控制對數據和代碼的訪問。

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");
                }
}

當然,對一個對象的更改不會影響另一個對象。 假設你有一個班級學生 ,你學校的所有孩子都是它的對象。 如果一個人離開學校,這並不意味着,每個其他學生(學生班的對象)也應該離開學校。

封裝是將您的類變量設置為私有的概念,因此沒有人可以直接與外部世界的數據成員一起玩。 但是你提供了公共方法,讓外部世界與你的數據成員一起玩,就像你想要的那樣。 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";

編譯器不允許你這樣做。 因為您無權訪問私人會員。

封裝的概念是一種與信息隱藏相關的設計技術。 基本原則是通過精心設計的界面提供對類屬性的受保護訪問。 封裝的目的是強制類的不變量。

要繼續您的示例,請考慮此類的接口:

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;
  }
}

在此示例中,對象不是不可變的,但其狀態是封裝的,因為只有通過訪問器和修飾符才能訪問它。 請注意封裝如何幫助您保護對象狀態的不變量。 通過方法約束修改,您可以更好地控制對象狀態的修改方式,添加驗證以確保任何修改與類的規范一致。

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;
}

encapsulation = VARIABLES(let private a,b,c)+ METHODS(setA&getA,setB&getB ....)我們可以使用private修飾符進行封裝。 讓我們考慮你創建的一個公共變量和一個私有變量...如果你必須將這些變量提供給另一個只讀類(只有他們可以看到並且無法修改),就不可能公共變量或方法,但我們可以通過提供get方法私下完成。 所以你的類私有變量或方法在你的控制之下。 但在公共場合沒有機會....我想你可以理解。

在運行Employee類時獲得輸出“print employees details:0 null”的原因是因為這些變量未初始化。 也就是說,您不在Employee類中為它們分配任何值。

無論您在EmployeeTest類中執行什么操作,都不會在下次運行時影響Employee中的變量值。 將每個Java程序運行視為“干凈的平板”。

在封裝方面,你真的不應該使用static關鍵字。 如果您要進行封裝,請查看此問題的其他答案,它有一個很好的代碼示例供您使用。

封裝是OOP概念。 該類被視為包含數據+行為的包。 數據應該是私有的,只能使用名為getters和setter的公共方法訪問。 您可以查看此封裝教程以獲取有關此概念的更多信息。

封裝是將方法和變量包裝在一起作為一個單元的機制。 例如膠囊,即混合了幾種葯物。

類的變量將從其他類中隱藏,因為它將被聲明為私有,並且只能通過其當前類的方法訪問

在Java中實現封裝 - *將類的變量聲明為私有。 *提供公共setter和getter方法來修改和查看變量值。 * Java Bean類是完全封裝類的示例。

你的意思是說empid的值應該是10而empname tom而不是0和null,如果是,那么 - :

1)變量的內存在運行時分配,並在程序終止后解除分配。

2)因此,如果你認為如果你給10提供一次它應該總是10,那就不是這樣,因為empid只是對存儲“10”的存儲器的引用。

3)因此,通過解除分配,我的意思是在程序終止之后,empid不再指向存儲10的存儲區域

4)每當執行一個新程序時,empid現在指向其他內存區域,並且在靜態變量的情況下,根據相應的數據類型為該內存分配默認值。 因此總是0和null。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM