EncapsulationHomepage  « Learn Java5 « Encapsulation

Up until now we haven't really worried about our data and how we expose it to the outside world. Before we do, lets take a step back and explain what we mean by exposing our data. Taking our Cat class test methods as an example; we have been happily writing code such as moggy.age = 12; without a care in the world to make sure our Cat class behaves as we expect. We could just have easily written moggy.age = 999; or moggy.age = -234; and the code would have worked just fine. Of course we could have verified the values we sent to our Cat class before we sent them, but this would have cluttered the code. Even if we had done this, there was nothing in place to stop any other program from making changes to our Cat members. In the real world we can't expose data like this, and we learn not to, as we look at encapsulation.

So what can we do about protecting our data and what is encapsulation? Encapsulation is a language mechanism used to restrict access to an object's components. In Java parlance this is a mechanism to restrict access to the members (instance variables and methods) of a class, constructors and even to the class itself. So how do we achieve this in Java?. Well Java provides us with the access modifier mechanism for restricting access to our classes, which are the basic unit of encapsulation in Java. We can also restrict access to our instance variables whilst providing access to them via public methods. We can limit construction to the class itself using the private keyword, or to the package the implementation is in using the protected keyword or with no modifier package-private / (the default). We have already seen the public access modifier used throughout the lessons and now it's time to go into access modifiers in more detail.

Access Modifiersgo to top of page Top

The table below shows the four types of access available in Java from the most open (public) to the most restrictive (private). We can only explicitly apply the public access modifier to our top-level classes (the classes we compile) but for members and constructors we can explicitly apply the protected and private access modifiers as well. We will talk about packaging in the Packages lesson, but for now we are going to examine how to protect our class members from unwanted access and modification.

Access modifier Class Member Constructor Description
publicYesYesYesA top-level class may be declared with the public access modifier, and if it is the class is accessible to all other classes everywhere.
A member may be declared with the public access modifier, and if it is the member is accessible to all other classes everywhere, assuming the class it resides in is accessible.
A constructor may be declared with the public access modifier, and if it is the constructor is accessible to all other classes everywhere, assuming the class it resides in is accessible.
protectedNoYesYesA member may be declared with the protected access modifier, and if so, is only accessible within its own package and also by a subclass of its class in other packages.
A constructor may be declared with the protected access modifier, and if so, it is only accessible to the package the implementation is in.

See the Packages lesson for more information on packaging.
See the Inheritance Basics lesson for more information on subclassing.
no modifier
package-private /
(the default)
YesYesYesIf a top-level class has no explicit access modifier, which is the default and is also known as package-private, it is accessible only within its own package.
If a member has no explicit access modifier it is only accessible within its own package.
If a constructor has no explicit access modifier, it is only accessible to the package the implementation is in.

See the Packages lesson for more information on packaging.
privateNoYesYesA member may be declared with the private access modifier, and if it is the member is only accessible within its own class.
A constructor may be declared with the private access modifier, and if it is the constructor can only be constructed from within its own class.

Protecting Our Datago to top of page Top

So now we know what encapsulation is and the access modifier mechanism Java uses to enforce it, how do we go about coding it? The following diagram is atypical of the classes we have written before and shows how our data is exposed:

encap 1

Creating A Folder For Our OO Concepts Source Files

As we are about to do the first code example of a new section lets create a folder for our OO Concepts files, in Windows this would be:

double click My Computer icon

double click C:\ drive (or whatever your local drive is)

right click the mouse in the window

from the drop down menu Select New

click the Folder option and call the folder _OOConcepts and press enter.

Safeguarding Instance Variablesgo to top of page Top

In the diagram above we unknowingly exposed our instance variables; by not setting an access modifier for them, they can now be tampered with by any class within the same package (package-default). So lets correct this issue by giving our instance variables the private access modifier so these members are only accessible within the Monkey class.


/*
  A Monkey Class
*/ 
public class Monkey {
    private String type;
    private int age;
}

Save and compile our Monkey class in directory   c:\_OOConcepts in the usual way.

Ok our instance variables have the private access modifier so these members are only accessible within the Monkey class. Now lets test our new Monkey class:


/*
  Test Class for Monkey
*/ 
public class TestMonkey {

    public static void main (String[] args) {
        Monkey mojo = new Monkey();
        mojo.type = "Orangutan";
        mojo.age = 25;
        System.out.println("Our " + mojo.type + " is " + mojo.age);
    }
}

Save and compile the file in directory   c:\_OOConcepts in the usual way.

run cat class with constructor

The above screenshot shows the output of running our getters and setter methods. It doesn't compile because we are trying to access private members of the class which can only be accessed from withinside the class. This is exactly what we want to protect our data, but how do we ever change a private instance variable then? We allow access to the private members of a class through the use of public methods.

Getters & Settersgo to top of page Top

So what we need are some public methods to get to our data. These are known as accessors and mutators or getters and setters. The convention when naming these methods is taken from a JavaBeans standard of get<someProperty> and set<someProperty>. This convention was included as part of the certification but has been removed, but it is still a standard and so will be used here. We will also refer to these methods as getters and setters. Ok lets revamp our Monkey class to include getters and setter methods so we can access or modify our instance variables:


/*
  A Monkey Class
*/ 
public class Monkey {
    private String type;
    private int age;
    /*
      Public getters and Setters
    */ 
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

Save and compile our reworked Monkey class in directory   c:\_OOConcepts in the usual way.

When we name our getter and setter methods we use the name of the instance variable and capitalize the first letter. We then prefix this with get or set to adhere to the JavaBeans standard. The other thing we must ensure to keep to this standard; is that all getter methods are not passed an argument and return a type, and that all setters methods are passed one argument and have a void return type.

Ok we should now be able to access our instance variables through the public getter and setter methods. Lets revamp our TestMonkey class to make sure our reworked Monkey class is working as expected:


/*
  Test Class for Monkey
*/ 
public class TestMonkey {

    public static void main (String[] args) {
        Monkey mojo = new Monkey();
        mojo.setType("Orangutan");
        mojo.setAge(25);
        System.out.println("Our " + mojo.getType() + " is " + mojo.getAge());
    }
}

Save, run and compile the file in directory   c:\_OOConcepts in the usual way.

run getset

The above screenshot shows the output of running our TestMonkey class. The reworked Monkey class works fine now and we have encapsulated our data so it is only accessible through the public getter and setter methods. Most of the time, what we have done in this lesson is all we need to encapsulate our data; other situations, with regards to inheritance and packaging, are covered in the appropriate lessons.

We haven't bothered with validation as the gist of the lesson is about encapsulation not validation. But it's good to know that we can now do all our validation within our setter methods, safe in the knowledge that if we need to change anything we aren't going to break other code elsewhere. This also means that the validation is in one place and only changes in one place, reducing maintenance and increasing reusability.

Encapsulation Quizgo to top of page Top

Try the quiz below to test your knowledge of this lesson

Question 1 : What mechanism is used for encapsulation in Java?
- We use <em>access modifiers</em> as our mechanism for encapsulation in Java.
Question 2 : Which access modifiers can we explicitly apply to our top-level classes?
- We can only explicitly apply the <code>public</code> <em>access modifiers</em> to our top-level classes.
Question 3 : Which access modifiers can we explicitly apply to our members?
- We can explicitly apply the <code>private</code>, <code>protected</code> or <code>public</code> <em>access modifiers</em> to our members.
Question 4 : Which access modifier limits member visibility to the class they reside in?
- The <code>private</code> <em>access modifiers</em> limits member visibility to the class they reside in.
Question 5 : How do we gain access to the private instance variables of a class?
- We gain access to the <code>private</code> instance variables of a class using <code>public</code> methods of the called class.
Question 6 : Does the following code conform to the JavaBean standard for getting the value of an instance variable called bootWidth?

public String getbootWidth() { return type; }
- The name of the method should be <code>getBootWidth()</code> to conform, the rest is fine.
Question 7 : Does the following code conform to the JavaBean standard for setting the value of an instance variable called bootWidth?

public int setBootWidth(int width) { this.width = width; }
- Setter methods should always have a <code>void</code> return type to conform, the rest is fine.
Status Bar Please select an answer

What's Next?

In the next lesson we learn about the various ways to code nested classes within our classes.

<<  OO Concepts                    Inheritance Basics  >>

go to home page Java5 Tutor Homepage go to top of page Top