logo

طريقة Getter وSetter في مثال Java

يتم استخدام أساليب Getter وSetter بشكل متكرر في برمجة Java. طرق Getter وSetter في Java تُستخدم على نطاق واسع للوصول إلى قيم حقول الفصل ومعالجتها. عادة، يتم تزيين حقول الفئة بمحدد وصول خاص. وبالتالي، للوصول إليها، يتم استخدام محددات الوصول العامة مع طريقتي getter وsetter.

الحاجة إلى طريقة Getter وSetter

يمكن للمرء أن يجادل بأن إعلان حقول الفئة عامة وإزالة أساليب getter و setter. ومع ذلك، فإن أسلوب الترميز هذا سيئ، وقد يضع المرء بعض القيمة السخيفة في حقول الفصل. دعونا نفهم ذلك بمساعدة مثال.

 public class GetterSetterExample { public salary; public storeSalaryDB(int salary) { // code for storing the salary in the database } // main method public static void main(String argvs[]) { GetterSetterExample obj = new GetterSetterExample(); obj.salary = -50000; // storing salary in database obj.storeSalaryDB(salary); } } 

لاحظ أن الكود يخزن راتبًا سالبًا في قاعدة البيانات وهذا خطأ. لا تقوم أي منظمة أبدًا بإيداع راتب سلبي في حساب الموظف. حدث تعيين مبلغ سخيف لمتغير الراتب لأنه تم الإعلان عنه باستخدام محدد وصول عام. الطريقة الصحيحة لكتابة الكود أعلاه هي:

 public class GetterSetterExample { private salary; // a setter method that assign a // value to the salary variable void setSalary(int s) { if(s <0 ) { s="-s;" } this.salary="s;" a getter mehtod to retrieve the salary int getsalary() return this.salary; public storesalarydb(int salary) code for storing in database system.out.println('the ') main method static void main(string argvs[]) creating an object of class gettersetterexample obj="new" gettersetterexample(); obj.setsalary(-50000); obj.storesalarydb(salary); < pre> <p>Now, we can see better control over what we send to the database to store. Whenever the salary is negative, we are converting the salary into a positive value, and then we are sending it to the database to store. Thus, no matter what value we send to the setter method, the if-block of the setter method takes care of the absurd value and thus gives better control on the salary value.</p> <h2>Getter Setter Java Program</h2> <p> <strong>FileName:</strong> GetterSetterExample1.java</p> <pre> class Employee { // class member variable private int eId; private String eName; private String eDesignation; private String eCompany; public int getEmpId() { return eId; } public void setEmpId(final int eId) { this.eId = eId; } public String getEmpName() { return eName; } public void setEmpName(final String eName) { // Validating the employee&apos;s name and // throwing an exception if the name is null or its length is less than or equal to 0. if(eName == null || eName.length() <= 0) { throw new illegalargumentexception(); } this.ename="eName;" public string getempdesignation() return edesignation; void setempdesignation(final edesignation) this.edesignation="eDesignation;" getempcompany() ecompany; setempcompany(final ecompany) this.ecompany="eCompany;" for printing the values @override tostring() str="Employee: [id = " + getempid() ', name=" + getEmpName() + " , designation=" + getEmpDesignation() + " company=" + getEmpCompany() + " ]'; str; main class. class gettersetterexample1 method static main(string argvs[]) creating an object of employee final emp="new" employee(); details are getting set using setter methods. emp.setempid(107); emp.setempname('kathy'); emp.setempdesignation('software tester'); emp.setempcompany('xyz corporation'); displaying 'tostring()' method, which uses getter methods system.out.println(emp.tostring()); < pre> <p> <strong>Output:</strong> </p> <pre> Employee: [id = 107, name = Kathy, designation = Software Tester, company = XYZ Corporation] </pre> <h2>Bad Practices in Getter and Setter Methods</h2> <p>There are some common bad practices that people usually do when they deal with the getter and setter methods.</p> <h3>Bad Practice 1:</h3> <p>Using getter and setter for the variable that is declared with low restricted scope.</p> <pre> public salary; void setSalary(int s) { salary = s; } int getSalary() { return salary; } </pre> <p>It is evident that from the main method, one can directly access the variable salary, which is not only bad but also makes the presence of the getter and setter methods irrelevant.</p> <h3>Bad Practice 2:</h3> <p>Using an object reference in the setter method. Consider the following program.</p> <p> <strong>FileName:</strong> GetterSetterExample2.java</p> <pre> class ABC { private int[] val; void setVal(int[] arr) { this.val = arr; // line 7 } // for displaying the value // present in the val array void display() { int size = (this.val).length; for(int i = 0; i <size; i++) { system.out.print(this.val[i] + ' '); } main class public gettersetterexample2 method static void main(string argvs[]) instantiating the abc obj="new" abc(); int mainarr[]="{3," 4, 6, 8, 78, 9}; invoking setter obj.setval(mainarr); display obj.display(); updating value at 0th index mainarr[0]="-1;" system.out.println(); < pre> <p> <strong>Output:</strong> </p> <pre> 3 4 6 8 78 9 -1 4 6 8 78 9 </pre> <p> <strong>Explanation:</strong> </p> <p>References are a bit tricky to deal with! In the above code, at line 43, the value got updated at the 0th index for array mainArr[]. However, it also got reflected in the array val[]. It should not happen as val[] array is declared private; hence, it is expected that any code outside of the class ABC should not modify it. However, because of the references, everything is messed up. The setter method setVal() expecting a reference of an int array, and at line 7, the reference of the int arr[] is getting copied to val[]. Note that the reference variable arr[] is storing the reference of the array mainArr[]. Thus, we can say val[] is storing the reference of the mainArr[].</p> <p>Therefore, whatever we change in the mainArr[] also gets reflected in the val[] array, which violates the purpose of the setter method. Also, there is no meaning in adding the private access specifier to the val[] array; because one can change the value of the val[] array in the main method, which is evident by looking at the output.</p> <p>A better way of writing the above code is:</p> <p> <strong>FileName:</strong> GetterSetterExample3.java</p> <pre> class ABC { private int[] val; void setVal(int[] arr) { int size = arr.length; // allocating the memory as // per the array arr size val = new int[size]; // line 11 for(int i = 0; i <size; 17 53 i++) { copying the value one by into val array this.val[i]="arr[i];" line } for displaying present in void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + ' '); main class. public class gettersetterexample3 method static main(string argvs[]) instantiating abc obj="new" abc(); mainarr[]="{3," 4, 6, 8, 78, 9}; invoking setter obj.setval(mainarr); display obj.display(); updating at 0th index mainarr[0]="-1;" system.out.println(); again pre> <p> <strong>Output:</strong> </p> <pre> 3 4 6 8 78 9 3 4 6 8 78 9 </pre> <p> <strong>Explanation:</strong> </p> <p>In the above code, we are doing the deep copy of elements of the array arr[]. In line 11, we are creating an entirely new array. Thus, the val[] is not referring to the arr[]. Also, in line 17, only values of the element are getting copied. Therefore, when we change the value of the 0th element at line 53, the change is not reflected in the val[]. Thus, the above code respects the encapsulation of the private member variable val[].</p> <h3>Bad Practice 3:</h3> <p>Returning an object reference in the getter method. Observe the following program.</p> <p> <strong>FileName:</strong> GetterSetterExample4.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { // returning the reference return val; // line 9 } // for displaying the value // present in the val array void display() { int size = (this.val).length; for(int i = 0; i <size; 42 i++) { system.out.print(this.val[i] + ' '); } main class. public class gettersetterexample4 method static void main(string argvs[]) instantiating the abc obj="new" abc(); invoking getter and storing result int arr[]="obj.getVal();" display obj.display(); updating value at 0th index arr[0]="-1;" line system.out.println(); again < pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 -1 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> </p> <p>The above code is not handling the references properly. The getter method is returning the reference of the array. The arr[] is storing the reference of the array val[], which is declared private in the class ABC. Because of exposing the reference to the outer world, arr[] can manipulate the val[], and thus, the encapsulation of the class ABC is breached. The proper way to handle the above is:</p> <p> <strong>FileName:</strong> GetterSetterExample5.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { int size = val.length; // creating a new array int temp[] = new int[size]; // copying the content of the array to temp array for(int i = 0; i <size; 54 i++) { temp[i]="val[i];" } return temp; for displaying the value present in val array void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + ' '); main class. public class gettersetterexample5 method static main(string argvs[]) instantiating abc obj="new" abc(); invoking getter and storing result arr[]="obj.getVal();" display obj.display(); updating at 0th index arr[0]="-1;" line system.out.println(); pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 67 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> In the above code, the reference of the private array is not sent to the outside world. In the getter method, a new array is created whose reference is sent to the main method. Therefore, when the value at the 0th index gets changed at line 54, that change impacts the temp[] array, not the private array val[]. Thus, the encapsulation of the class ABC is maintained, as the reference of the array val[] is not exposed to the outside world.</p> <h4>Note 1: For primitive data types (int, char, etc.), one does not need to create a copy in the getter and setter methods, as the concept of references is absent for the primitive data types.</h4> <h4>Note 2: Strings object types also work on the references. However, unlike the above examples, one does not need to take care of the String references exposed to the outside world. It is because Strings are immutable. Thus, when one manipulates the string in the main method (or anywhere else), a new String object is created, and the previous one remains untouched.</h4> <p> <strong>FileName:</strong> GetterSetterExample6.java</p> <pre> class ABC { private String str = null; // a setter method void setVal(String s) { // reference is getting copied this.str = s; } // for displaying the string void display() { System.out.println( &apos;The String is: &apos; + this.str); } } // Main class. public class GetterSetterExample6 { // main method public static void main(String argvs[]) { // creating an object of the class ABC ABC obj = new ABC(); // input string String inputStr = &apos;Hello India!&apos;; // invoking the setter method obj.setVal(inputStr); obj.display(); // manipulation is not allowed! // it leads to the creation of the new string inputStr = &apos;Hello World!&apos;; obj.display(); } } </pre> <p> <strong>Output:</strong> </p> <pre> The String is: Hello India! The String is: Hello India! </pre> <hr></size;></pre></size;></pre></size;></pre></size;></pre></=></pre></0>

الممارسات السيئة في طرق Getter وSetter

هناك بعض الممارسات السيئة الشائعة التي يقوم بها الأشخاص عادةً عند التعامل مع طرق الضبط والضبط.

دوران شجرة AVL

الممارسة السيئة 1:

استخدام getter وsetter للمتغير الذي تم الإعلان عنه بنطاق مقيد منخفض.

 public salary; void setSalary(int s) { salary = s; } int getSalary() { return salary; } 

من الواضح أنه من خلال الطريقة الرئيسية، يمكن للمرء الوصول مباشرة إلى الراتب المتغير، وهو ليس سيئًا فحسب، بل يجعل أيضًا وجود طريقتي getter وsetter غير ذي صلة.

الممارسة السيئة 2:

استخدام مرجع كائن في طريقة الضبط. النظر في البرنامج التالي.

اسم الملف: GetterSetterExample2.java

 class ABC { private int[] val; void setVal(int[] arr) { this.val = arr; // line 7 } // for displaying the value // present in the val array void display() { int size = (this.val).length; for(int i = 0; i <size; i++) { system.out.print(this.val[i] + \' \'); } main class public gettersetterexample2 method static void main(string argvs[]) instantiating the abc obj="new" abc(); int mainarr[]="{3," 4, 6, 8, 78, 9}; invoking setter obj.setval(mainarr); display obj.display(); updating value at 0th index mainarr[0]="-1;" system.out.println(); < pre> <p> <strong>Output:</strong> </p> <pre> 3 4 6 8 78 9 -1 4 6 8 78 9 </pre> <p> <strong>Explanation:</strong> </p> <p>References are a bit tricky to deal with! In the above code, at line 43, the value got updated at the 0th index for array mainArr[]. However, it also got reflected in the array val[]. It should not happen as val[] array is declared private; hence, it is expected that any code outside of the class ABC should not modify it. However, because of the references, everything is messed up. The setter method setVal() expecting a reference of an int array, and at line 7, the reference of the int arr[] is getting copied to val[]. Note that the reference variable arr[] is storing the reference of the array mainArr[]. Thus, we can say val[] is storing the reference of the mainArr[].</p> <p>Therefore, whatever we change in the mainArr[] also gets reflected in the val[] array, which violates the purpose of the setter method. Also, there is no meaning in adding the private access specifier to the val[] array; because one can change the value of the val[] array in the main method, which is evident by looking at the output.</p> <p>A better way of writing the above code is:</p> <p> <strong>FileName:</strong> GetterSetterExample3.java</p> <pre> class ABC { private int[] val; void setVal(int[] arr) { int size = arr.length; // allocating the memory as // per the array arr size val = new int[size]; // line 11 for(int i = 0; i <size; 17 53 i++) { copying the value one by into val array this.val[i]="arr[i];" line } for displaying present in void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + \' \'); main class. public class gettersetterexample3 method static main(string argvs[]) instantiating abc obj="new" abc(); mainarr[]="{3," 4, 6, 8, 78, 9}; invoking setter obj.setval(mainarr); display obj.display(); updating at 0th index mainarr[0]="-1;" system.out.println(); again pre> <p> <strong>Output:</strong> </p> <pre> 3 4 6 8 78 9 3 4 6 8 78 9 </pre> <p> <strong>Explanation:</strong> </p> <p>In the above code, we are doing the deep copy of elements of the array arr[]. In line 11, we are creating an entirely new array. Thus, the val[] is not referring to the arr[]. Also, in line 17, only values of the element are getting copied. Therefore, when we change the value of the 0th element at line 53, the change is not reflected in the val[]. Thus, the above code respects the encapsulation of the private member variable val[].</p> <h3>Bad Practice 3:</h3> <p>Returning an object reference in the getter method. Observe the following program.</p> <p> <strong>FileName:</strong> GetterSetterExample4.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { // returning the reference return val; // line 9 } // for displaying the value // present in the val array void display() { int size = (this.val).length; for(int i = 0; i <size; 42 i++) { system.out.print(this.val[i] + \' \'); } main class. public class gettersetterexample4 method static void main(string argvs[]) instantiating the abc obj="new" abc(); invoking getter and storing result int arr[]="obj.getVal();" display obj.display(); updating value at 0th index arr[0]="-1;" line system.out.println(); again < pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 -1 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> </p> <p>The above code is not handling the references properly. The getter method is returning the reference of the array. The arr[] is storing the reference of the array val[], which is declared private in the class ABC. Because of exposing the reference to the outer world, arr[] can manipulate the val[], and thus, the encapsulation of the class ABC is breached. The proper way to handle the above is:</p> <p> <strong>FileName:</strong> GetterSetterExample5.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { int size = val.length; // creating a new array int temp[] = new int[size]; // copying the content of the array to temp array for(int i = 0; i <size; 54 i++) { temp[i]="val[i];" } return temp; for displaying the value present in val array void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + \' \'); main class. public class gettersetterexample5 method static main(string argvs[]) instantiating abc obj="new" abc(); invoking getter and storing result arr[]="obj.getVal();" display obj.display(); updating at 0th index arr[0]="-1;" line system.out.println(); pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 67 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> In the above code, the reference of the private array is not sent to the outside world. In the getter method, a new array is created whose reference is sent to the main method. Therefore, when the value at the 0th index gets changed at line 54, that change impacts the temp[] array, not the private array val[]. Thus, the encapsulation of the class ABC is maintained, as the reference of the array val[] is not exposed to the outside world.</p> <h4>Note 1: For primitive data types (int, char, etc.), one does not need to create a copy in the getter and setter methods, as the concept of references is absent for the primitive data types.</h4> <h4>Note 2: Strings object types also work on the references. However, unlike the above examples, one does not need to take care of the String references exposed to the outside world. It is because Strings are immutable. Thus, when one manipulates the string in the main method (or anywhere else), a new String object is created, and the previous one remains untouched.</h4> <p> <strong>FileName:</strong> GetterSetterExample6.java</p> <pre> class ABC { private String str = null; // a setter method void setVal(String s) { // reference is getting copied this.str = s; } // for displaying the string void display() { System.out.println( &apos;The String is: &apos; + this.str); } } // Main class. public class GetterSetterExample6 { // main method public static void main(String argvs[]) { // creating an object of the class ABC ABC obj = new ABC(); // input string String inputStr = &apos;Hello India!&apos;; // invoking the setter method obj.setVal(inputStr); obj.display(); // manipulation is not allowed! // it leads to the creation of the new string inputStr = &apos;Hello World!&apos;; obj.display(); } } </pre> <p> <strong>Output:</strong> </p> <pre> The String is: Hello India! The String is: Hello India! </pre> <hr></size;></pre></size;></pre></size;></pre></size;>

توضيح:

المراجع صعبة بعض الشيء للتعامل معها! في الكود أعلاه، في السطر 43، تم تحديث القيمة في الفهرس 0 للمصفوفة mainArr[]. ومع ذلك، فقد انعكست أيضًا في قيمة المصفوفة[]. لا ينبغي أن يحدث ذلك عندما يتم إعلان صفيف val[] خاصًا؛ وبالتالي، من المتوقع ألا يقوم أي كود خارج الفئة ABC بتعديله. ومع ذلك، بسبب المراجع، افسدت كل شيء. تتوقع طريقة الضبط setVal() مرجعًا لمصفوفة int، وفي السطر 7، يتم نسخ مرجع int arr[] إلى val[]. لاحظ أن المتغير المرجعي arr[] يقوم بتخزين مرجع المصفوفة mainArr[]. وبالتالي، يمكننا القول أن val[] يقوم بتخزين مرجع mainArr[].

كم مدينة في الولايات المتحدة الأمريكية

لذلك، كل ما نقوم بتغييره في mainArr[] ينعكس أيضًا في مصفوفة val[]، مما ينتهك غرض طريقة الضبط. أيضًا، ليس هناك أي معنى لإضافة محدد الوصول الخاص إلى المصفوفة val[]؛ لأنه يمكن تغيير قيمة مصفوفة val[] في الطريقة الرئيسية، وهو ما يتضح من خلال النظر إلى الإخراج.

أفضل طريقة لكتابة الكود أعلاه هي:

اسم الملف: GetterSetterExample3.java

 class ABC { private int[] val; void setVal(int[] arr) { int size = arr.length; // allocating the memory as // per the array arr size val = new int[size]; // line 11 for(int i = 0; i <size; 17 53 i++) { copying the value one by into val array this.val[i]="arr[i];" line } for displaying present in void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + \' \'); main class. public class gettersetterexample3 method static main(string argvs[]) instantiating abc obj="new" abc(); mainarr[]="{3," 4, 6, 8, 78, 9}; invoking setter obj.setval(mainarr); display obj.display(); updating at 0th index mainarr[0]="-1;" system.out.println(); again pre> <p> <strong>Output:</strong> </p> <pre> 3 4 6 8 78 9 3 4 6 8 78 9 </pre> <p> <strong>Explanation:</strong> </p> <p>In the above code, we are doing the deep copy of elements of the array arr[]. In line 11, we are creating an entirely new array. Thus, the val[] is not referring to the arr[]. Also, in line 17, only values of the element are getting copied. Therefore, when we change the value of the 0th element at line 53, the change is not reflected in the val[]. Thus, the above code respects the encapsulation of the private member variable val[].</p> <h3>Bad Practice 3:</h3> <p>Returning an object reference in the getter method. Observe the following program.</p> <p> <strong>FileName:</strong> GetterSetterExample4.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { // returning the reference return val; // line 9 } // for displaying the value // present in the val array void display() { int size = (this.val).length; for(int i = 0; i <size; 42 i++) { system.out.print(this.val[i] + \' \'); } main class. public class gettersetterexample4 method static void main(string argvs[]) instantiating the abc obj="new" abc(); invoking getter and storing result int arr[]="obj.getVal();" display obj.display(); updating value at 0th index arr[0]="-1;" line system.out.println(); again < pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 -1 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> </p> <p>The above code is not handling the references properly. The getter method is returning the reference of the array. The arr[] is storing the reference of the array val[], which is declared private in the class ABC. Because of exposing the reference to the outer world, arr[] can manipulate the val[], and thus, the encapsulation of the class ABC is breached. The proper way to handle the above is:</p> <p> <strong>FileName:</strong> GetterSetterExample5.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { int size = val.length; // creating a new array int temp[] = new int[size]; // copying the content of the array to temp array for(int i = 0; i <size; 54 i++) { temp[i]="val[i];" } return temp; for displaying the value present in val array void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + \' \'); main class. public class gettersetterexample5 method static main(string argvs[]) instantiating abc obj="new" abc(); invoking getter and storing result arr[]="obj.getVal();" display obj.display(); updating at 0th index arr[0]="-1;" line system.out.println(); pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 67 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> In the above code, the reference of the private array is not sent to the outside world. In the getter method, a new array is created whose reference is sent to the main method. Therefore, when the value at the 0th index gets changed at line 54, that change impacts the temp[] array, not the private array val[]. Thus, the encapsulation of the class ABC is maintained, as the reference of the array val[] is not exposed to the outside world.</p> <h4>Note 1: For primitive data types (int, char, etc.), one does not need to create a copy in the getter and setter methods, as the concept of references is absent for the primitive data types.</h4> <h4>Note 2: Strings object types also work on the references. However, unlike the above examples, one does not need to take care of the String references exposed to the outside world. It is because Strings are immutable. Thus, when one manipulates the string in the main method (or anywhere else), a new String object is created, and the previous one remains untouched.</h4> <p> <strong>FileName:</strong> GetterSetterExample6.java</p> <pre> class ABC { private String str = null; // a setter method void setVal(String s) { // reference is getting copied this.str = s; } // for displaying the string void display() { System.out.println( &apos;The String is: &apos; + this.str); } } // Main class. public class GetterSetterExample6 { // main method public static void main(String argvs[]) { // creating an object of the class ABC ABC obj = new ABC(); // input string String inputStr = &apos;Hello India!&apos;; // invoking the setter method obj.setVal(inputStr); obj.display(); // manipulation is not allowed! // it leads to the creation of the new string inputStr = &apos;Hello World!&apos;; obj.display(); } } </pre> <p> <strong>Output:</strong> </p> <pre> The String is: Hello India! The String is: Hello India! </pre> <hr></size;></pre></size;></pre></size;>

توضيح:

في الكود أعلاه، نقوم بعمل نسخة عميقة لعناصر المصفوفة arr[]. في السطر 11، قمنا بإنشاء مصفوفة جديدة تمامًا. وبالتالي، فإن val[] لا يشير إلى arr[]. أيضًا، في السطر 17، يتم نسخ قيم العنصر فقط. لذلك، عندما نغير قيمة العنصر 0 في السطر 53، لا ينعكس التغيير في القيمة val[]. وبالتالي، فإن الكود أعلاه يحترم تغليف متغير العضو الخاص val[].

نات مقابل السرير

الممارسة السيئة 3:

إرجاع مرجع كائن في طريقة getter. لاحظ البرنامج التالي

كم عدد الأسابيع في الشهر

اسم الملف: GetterSetterExample4.java

 class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { // returning the reference return val; // line 9 } // for displaying the value // present in the val array void display() { int size = (this.val).length; for(int i = 0; i <size; 42 i++) { system.out.print(this.val[i] + \' \'); } main class. public class gettersetterexample4 method static void main(string argvs[]) instantiating the abc obj="new" abc(); invoking getter and storing result int arr[]="obj.getVal();" display obj.display(); updating value at 0th index arr[0]="-1;" line system.out.println(); again < pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 -1 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> </p> <p>The above code is not handling the references properly. The getter method is returning the reference of the array. The arr[] is storing the reference of the array val[], which is declared private in the class ABC. Because of exposing the reference to the outer world, arr[] can manipulate the val[], and thus, the encapsulation of the class ABC is breached. The proper way to handle the above is:</p> <p> <strong>FileName:</strong> GetterSetterExample5.java</p> <pre> class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { int size = val.length; // creating a new array int temp[] = new int[size]; // copying the content of the array to temp array for(int i = 0; i <size; 54 i++) { temp[i]="val[i];" } return temp; for displaying the value present in val array void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + \' \'); main class. public class gettersetterexample5 method static main(string argvs[]) instantiating abc obj="new" abc(); invoking getter and storing result arr[]="obj.getVal();" display obj.display(); updating at 0th index arr[0]="-1;" line system.out.println(); pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 67 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> In the above code, the reference of the private array is not sent to the outside world. In the getter method, a new array is created whose reference is sent to the main method. Therefore, when the value at the 0th index gets changed at line 54, that change impacts the temp[] array, not the private array val[]. Thus, the encapsulation of the class ABC is maintained, as the reference of the array val[] is not exposed to the outside world.</p> <h4>Note 1: For primitive data types (int, char, etc.), one does not need to create a copy in the getter and setter methods, as the concept of references is absent for the primitive data types.</h4> <h4>Note 2: Strings object types also work on the references. However, unlike the above examples, one does not need to take care of the String references exposed to the outside world. It is because Strings are immutable. Thus, when one manipulates the string in the main method (or anywhere else), a new String object is created, and the previous one remains untouched.</h4> <p> <strong>FileName:</strong> GetterSetterExample6.java</p> <pre> class ABC { private String str = null; // a setter method void setVal(String s) { // reference is getting copied this.str = s; } // for displaying the string void display() { System.out.println( &apos;The String is: &apos; + this.str); } } // Main class. public class GetterSetterExample6 { // main method public static void main(String argvs[]) { // creating an object of the class ABC ABC obj = new ABC(); // input string String inputStr = &apos;Hello India!&apos;; // invoking the setter method obj.setVal(inputStr); obj.display(); // manipulation is not allowed! // it leads to the creation of the new string inputStr = &apos;Hello World!&apos;; obj.display(); } } </pre> <p> <strong>Output:</strong> </p> <pre> The String is: Hello India! The String is: Hello India! </pre> <hr></size;></pre></size;>

توضيح:

الكود أعلاه لا يتعامل مع المراجع بشكل صحيح. تقوم طريقة getter بإرجاع مرجع المصفوفة. يقوم arr[] بتخزين مرجع المصفوفة val[]، والتي تم الإعلان عنها بأنها خاصة في الفئة ABC. بسبب كشف المرجع إلى العالم الخارجي، يمكن لـ arr[] التعامل مع val[]، وبالتالي يتم اختراق تغليف الفئة ABC. الطريقة الصحيحة للتعامل مع ما سبق هي:

اسم الملف: GetterSetterExample5.java

 class ABC { private int[] val = {67, 43, 68, 112, 70, 12}; // the getter method public int[] getVal() { int size = val.length; // creating a new array int temp[] = new int[size]; // copying the content of the array to temp array for(int i = 0; i <size; 54 i++) { temp[i]="val[i];" } return temp; for displaying the value present in val array void display() int size="(this.val).length;" for(int i="0;" < size; system.out.print(this.val[i] + \\' \\'); main class. public class gettersetterexample5 method static main(string argvs[]) instantiating abc obj="new" abc(); invoking getter and storing result arr[]="obj.getVal();" display obj.display(); updating at 0th index arr[0]="-1;" line system.out.println(); pre> <p> <strong>Output:</strong> </p> <pre> 67 43 68 112 70 12 67 43 68 112 70 12 </pre> <p> <strong>Explanation:</strong> In the above code, the reference of the private array is not sent to the outside world. In the getter method, a new array is created whose reference is sent to the main method. Therefore, when the value at the 0th index gets changed at line 54, that change impacts the temp[] array, not the private array val[]. Thus, the encapsulation of the class ABC is maintained, as the reference of the array val[] is not exposed to the outside world.</p> <h4>Note 1: For primitive data types (int, char, etc.), one does not need to create a copy in the getter and setter methods, as the concept of references is absent for the primitive data types.</h4> <h4>Note 2: Strings object types also work on the references. However, unlike the above examples, one does not need to take care of the String references exposed to the outside world. It is because Strings are immutable. Thus, when one manipulates the string in the main method (or anywhere else), a new String object is created, and the previous one remains untouched.</h4> <p> <strong>FileName:</strong> GetterSetterExample6.java</p> <pre> class ABC { private String str = null; // a setter method void setVal(String s) { // reference is getting copied this.str = s; } // for displaying the string void display() { System.out.println( &apos;The String is: &apos; + this.str); } } // Main class. public class GetterSetterExample6 { // main method public static void main(String argvs[]) { // creating an object of the class ABC ABC obj = new ABC(); // input string String inputStr = &apos;Hello India!&apos;; // invoking the setter method obj.setVal(inputStr); obj.display(); // manipulation is not allowed! // it leads to the creation of the new string inputStr = &apos;Hello World!&apos;; obj.display(); } } </pre> <p> <strong>Output:</strong> </p> <pre> The String is: Hello India! The String is: Hello India! </pre> <hr></size;>

توضيح: في الكود أعلاه، لا يتم إرسال مرجع المصفوفة الخاصة إلى العالم الخارجي. في طريقة getter، يتم إنشاء مصفوفة جديدة يتم إرسال مرجعها إلى الطريقة الرئيسية. ولذلك، عندما تتغير القيمة في الفهرس 0 في السطر 54، فإن هذا التغيير يؤثر على المصفوفة المؤقتة[]، وليس على المصفوفة الخاصة val[]. وبالتالي، يتم الحفاظ على تغليف الفئة ABC، حيث لا يتم عرض مرجع المصفوفة val[] للعالم الخارجي.

ملاحظة 1: بالنسبة لأنواع البيانات البدائية (int، char، وما إلى ذلك)، لا يحتاج المرء إلى إنشاء نسخة باستخدام أسلوبي getter وsetter، حيث أن مفهوم المراجع غائب عن أنواع البيانات البدائية.

ملاحظة 2: أنواع كائنات السلاسل تعمل أيضًا على المراجع. ومع ذلك، على عكس الأمثلة المذكورة أعلاه، لا يحتاج المرء إلى الاهتمام بمراجع السلسلة المكشوفة للعالم الخارجي. فذلك لأن السلاسل غير قابلة للتغيير. وبالتالي، عندما يقوم شخص ما بمعالجة السلسلة في الطريقة الرئيسية (أو في أي مكان آخر)، يتم إنشاء كائن سلسلة جديد، ويظل الكائن السابق دون تغيير.

اسم الملف: GetterSetterExample6.java

 class ABC { private String str = null; // a setter method void setVal(String s) { // reference is getting copied this.str = s; } // for displaying the string void display() { System.out.println( &apos;The String is: &apos; + this.str); } } // Main class. public class GetterSetterExample6 { // main method public static void main(String argvs[]) { // creating an object of the class ABC ABC obj = new ABC(); // input string String inputStr = &apos;Hello India!&apos;; // invoking the setter method obj.setVal(inputStr); obj.display(); // manipulation is not allowed! // it leads to the creation of the new string inputStr = &apos;Hello World!&apos;; obj.display(); } } 

انتاج:

 The String is: Hello India! The String is: Hello India!