Encapsulation – CS2 – Java


In Java, the access specifier is included in each of the class’s variable and method declarations, preceding the  data type. Be careful! When no modifier is given, the default access specifier is public, meaning that methods in any class within the same package, or one that imports that package, will be able to use, access, or modify these members.

An example of a Java class declaration follows:

public class Time {
    private int hour;
    private int minute;
    private int second;

    public Time()
        { /* constructor implementation */ }
    public void setTime(int newHour, int newMinute, int newSecond)
        { /* mutator implementation */ }
    public int[] getTime()
        { /* accessor implementation */ }
    public void incrementTime()
        { /* mutator implementation */ }
}

In the example above, the data members hour, minute, and second and the member methods setTime(), getTime(), and incrementTime() are bundled into a single autonomous class named Time. This demonstrates the encapsulation feature of Java. When all data is declared as private, the data is only accessible through the methods provided by the class. This restricted access is illustrated below.

Such restricted access requires programmers to write specialized accessor methods like getTime() for acquiring the values of private data members and specialized mutator methods like setTime() and incrementTime() for performing operations on them. This allows programmers to validate changes to data members before making such a change. In this example, the setTime() method would be written to check for valid values for military time (hour is between 0 and 23 and minute and second are between 0 and 59.)

Encapsulation hides the private data members and the implementation details of a class, but it does not necessarily mean a class is completely isolated. Many objects must share information with other objects, usually with good reason. However, protecting private data by providing accessor and mutator methods ensures that an object is affected only in known ways by other objects in the system. Sharing should be minimized so that the class provides as few interfaces (public methods) as possible. Other methods required for the class should be private, so they are not available outside the class.

Using encapsulation properly and providing a controlled public interface is similar to a fast-food restaurant that has no indoor customer access and provides only a drive-up window. The customer can read the menu, place an order from the menu, pay for the order, and pick up the completed order. The customer does not know exactly what is occurring inside the restaurant; he or she knows only that placing an order and paying for it results in the food showing up in the completed order. The customer may return to the same fast-food restaurant every day for a month and interact with the restaurant in the same way. If the restaurant hires a consultant to cut costs and changes the way orders are filled, the customer has no knowledge of the change, and does not really need to know about it. As long as the customer interacts with the restaurant in the same way and the food tastes just as good each time, the customer does not really even care about the internal operations of the restaurant.

Proper use of encapsulation in Java enhances program security for several reasons:

  1. The initial value of all data members is controlled by the programmer writing the code for the class.
  2. Access to an object’s data is controlled by the programmer writing the code for the class, resulting in fewer human errors caused by improper use of the class by other programmers. Encapsulated objects that declare data as private or protected act as a black box, protecting the object’s data and allowing access to the data only by calling class member methods, which control how the data can be accessed and/or changed. Data is secure because it can only be accessed in a safe manner, in the same way that a bank account is secure because it can only be accessed in a safe manner.
  3. Encapsulated objects provide full functionality; however, calling objects do not know the implementation details, and cannot rely on or take advantage of a particular implementation. This means that the implementation can be enhanced or updated in the future without affecting calling objects.
  4. If a class is isolated from the effects of other classes in the program using encapsulation, it is easier to trace a fault to the class that caused it and to limit the damage caused by the fault.
READ:  TU | Color | TU Brand Toolkit

Risk – How can it happen?

If a programmer does not use encapsulation properly, the existence of the encapsulation feature in Java provides no enhanced security. In fact, using encapsulation improperly can greatly increase the insecurity of the program. Encapsulation violations increase program insecurities in direct proportion to how much intelligence the class contains. If the class stores one simple data element, such as a char, whose value can be any legal char value, then encapsulation violations are probably not a big issue. As the data becomes more complicated, encapsulation violations create more and more insecurities, since the special properties of the data (such as limiting hour to values between 0 and 23, inclusive) are more and more likely to be violated.

As the rules of proper encapsulation are violated, all clients of the class become responsible for more and more code to correctly access and use the object’s data. As the class is enhanced and updated over time, it is not possible to correct all uses of the class, particularly if external users are out of the programmer’s control. Eventually the class loses integrity entirely and becomes a security vulnerability.

Example in Code:

Consider the following class declaration:

public class RiskyTime {
    int hour;
    int minute;
    int second;
    void setTime(int newHour, int newMinute, int newSecond)
        { /* mutator implementation */ }
    int[] getTime()
        { /* accessor implementation */ }
    void incrementTime()
        { /* mutator implementation */ }
};

The RiskyTime class has no modesty; having not explicitly stated that its data should be considered private, they are hanging out in public for the entire program to see. The reason this is an issue for a class is the same reason it is a personal issue. When a person is exposed, he or she may get sunburned in all the wrong places. When data is exposed, other components have complete access to that data and can cause mischief. Since RiskyTime allows all methods in the entire program direct access to its data members, an external method could set hour, minute, and second to an invalid time, such as 36:99:-33 (hour:minute:second). Clients that use the class cannot count on the time being valid. If the client uses the class, anyway, and does not check to be sure the object’s data is valid every time it is used, the invalid values can cause strange, and even dangerous, things to occur when the program executes.

READ:  Are you able to give yourself the gift of forgiveness? Find out here!

Code Responsibly – how to encapsulate properly?

  1. Restrict access: Declare all data members as private. In addition, keep all methods that do not need to be called by external program components private. Create public methods to provide a controlled interface between the object’s data and all external program components.
  2. Know the limits: Familiarize yourself with the range of valid values for each data element being stored in the class.
  3. Initialize the data: Set all the data elements to valid initial values for an empty or non-existent object using a default constructor.
  4. Choose the data types wisely: For example, Java contains multiple data types for storing integer values. Be sure to choose integer types that are large enough to hold all the valid values that will be stored on each type of computer that will be used.
  5. Validate the input: Check input for validity before changing the data values stored in the object.
  6. Double check all operations performed: Be sure that any operations that change the data, such as incrementing the time, maintain the validity of all the data elements.

Lab Assignment

top

Program 1

// file Time.java
public class Time {
	final int MAX_HOURS = 23;
	final int MAX_MIN_SECS = 59;

	int hour;    // current hour in military time
	int minute;  // current minute in military time
	int second;  // current second in military time

	// set the time to the time specified by the parameters
	void setTime (int newHour, int newMinute, int newSecond) {
		hour = newHour;
		minute = newMinute;
		second = newSecond;
	}

	// return the time to the calling method in a three-membered array
	int[] getTime() {
		return new int[] {hour, minute, second};
	}

	// increment the current time by one second
	void incrementTime() {
		++second;
	}
}


// file Main.java
public class Main {
	public static void main(String[] args) {
		Time currTime = new Time();  // object that stores the current time
		int hr;         // current hour obtained from currTime
		int min;        // current minute obtained from currTime
		int sec;        // current second obtained from currTime
		
		int[] temp;		// for using getTime()

		currTime.setTime(20, 15, 43);
		temp = currTime.getTime();
		hr = temp[0];
		min = temp[1];
		sec = temp[2];
		
		System.out.println(
				"The current military time is set to: "
						+ hr + ":" + min + ":" + sec
				);

		
		currTime.incrementTime();
		temp = currTime.getTime();
		hr = temp[0];
		min = temp[1];
		sec = temp[2];
		
		System.out.println(
				"After incrementing the time, the current military time is: "
						+ hr + ":" + min + ":" + sec
				);
	}
}

Lab Questions:

  1. Type Program 1 above into the 2 separate files specified by the header comments. Compile and run the program.
  2. Look at the output. Does it make sense? Why or why not?
  3. Change the call to currTime.setTime() in main.java to the following:
    currTime.setTime(-55, 99, 1025);

    Compile and run the program.

  4. Look at the new output. Does it make sense? Why or why not?
  5. Add the following lines to Main.java just before the end of the main() method:
    		currTime.hour = 31;
    		currTime.minute = -10;
    		currTime.second = 450;
    		
    		temp = currTime.getTime();
    		hr = temp[0];
    		min = temp[1];
    		sec = temp[2];
    		
    		System.out.println(
    				"After direct assignment, the current military time is: "
    						+ hr + ":" + min + ":" + sec
    				);
    

    Compile and run the program.

  6. Look at the last line of output. Does it make sense? Why or why not?
  7. We need to fix the problem caused by declaring the data in the Time class as public. Change Time.java to make the 3 data declarations private. Compile the program. What happens? Why?
  8. Remove the lines that were added to Main.java in step 5 above. Compile and run the program.
  9. Now, let’s fix the setTime() method. Change it as shown below:
    	void setTime(int newHour, int newMinute, int newSecond) {
    		if (newHour >= 0 && newHour = 0 && newMinute = 0 && newSecond 
    

    Compile and run the program.

  10. Why is this version of the setTime() method more secure than the previous version?
  11. Look at the new output. Does it make sense? Why or why not?
  12. Change the call to currTime.setTime() in Main.java to the following:
    currTime.setTime(23, 59, 59);

    Compile and run the program.

  13. Look at the new output. Does it make sense? Why or why not?
  14. Add an appropriate constructor to the Time class. Compile and run the program.
  15. What values should be used to initialize hour, minute, and second in the constructor? Why are these times appropriate?
READ:  Trickle Down | Phrase Definition, Origin & Examples

*Copying and pasting programs may result in syntax errors and other inconsistencies. It is recommended you type each program.

 

Security Checklist

top

  1. Print Time.java and Main.java.
  2. Print the Security Checklist shown below and use the printouts to complete the checklist.

Security Checklist

Vulnerability: Improper Encapsulation Course: CS2  

Completed
1. Circle each private data member.  
2. Mark with a V each public data member.  
3. Underline the method header for each method that accesses the values of private data members,but does not change them  
4. Mark with a V the method header for each method that changes the value of any private data members.  
5. Mark with a C any constructors that initialize data members. C stands for constructor (see question #4 below.)  
Highlighted areas indicate vulnerabilities!  

Discussion Questions

top
  1. Why are public data members in a class a major security issue?
  2. Are accessor methods vulnerabilities in a class? Why or why not?
  3. Why is it important for a programmer to know the range of valid values for each data element being stored in the class?
  4. Is it acceptable to omit default constructors in a class? Why or why not?
  5. Why should the data types for class data members be chosen carefully?
  6. Why should a mutator method validate the input before changing the data values stored in an object?
  7. Why is it important for a programmer to double check any operations that change the value of class data members?

Further Work (optional – check with your instructor to see if you need to perform the following steps)

  1. Now, let’s fix the incrementTime() method. Change it as shown below:
    	void incrementTime () {
    		second = ++second % (MAX_MIN_SECS + 1);
    		
    		if(second == 0) {
    			minute = ++minute % (MAX_MIN_SECS + 1);
    		}
    		if(minute == 0) {
    			hour = ++hour % (MAX_HOURS + 1);
    		}
    	}
    

    Compile and run the program.

  2. Why is this version of the incrementTime() method more secure than the original version?
  3. Look at the new output. Does it make sense? Why or why not?
  4. Add the following lines to Main.java just before the call to currTime.setTime():
    		temp = currTime.getTime();
    		hr = temp[0];
    		min = temp[1];
    		sec = temp[2];
    		
    		System.out.println(
    				"The initial military time is set to: "
    						+ hr + ":" + min + ":" + sec
    				);
    

    Compile and run the program.

  5. Look at the first line of output. Does it make sense? Why or why not?


View more information: https://cisserv1.towson.edu/~cssecinj/modules/other-modules/build-the-lab/build-the-lab-lab-module-1/encapsulation-java/

See more articles in category: Grammar

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button