Search code examples
encapsulation

Encapsulation in Java when returning an object


Consider below example:

 public class sample{
     private Map myMap;

     public Map getMap(){

     return myMap;
     }
    }

In above example, we are returning the map to some other calling class. So my question is how we can say that this class encapsulates/protects its data. The Map that will be returned will be available for modification by other classes.

Thanks, Rajan


Solution

  • Consider this class Person, which have 2 attributes (name and age).

    package app;
    
    /**
     *
     * @author salathielgenese
     */
    public final class Person
    {
    
        public Person()
        {
            setAge(age);
            setName(name);
        }
    
        public Person(String name, long age)
        {
            setName(name);
            setAge(age);
        }
    
        public String getName()
        {
            return name;
        }
    
        public void setName(String name)
        {
            this.name = name;
        }
    
        public long getAge()
        {
            return age;
        }
    
        public void setAge(long age)
        {
            this.age = age;
        }
    
        private String name;
        private long age;
    }
    

    Now imagine that some one (let say the calling class) set the age to -19. This will generate inconsistency in your that.

    So when you protect your data, your controlling wich kind of action are made possible these data. You may decide that if the given age is lower than 0 then the age will be set to 0 for example. The code may become...

        public void setAge(long age)
        {
            this.age = age;
            if (age < 0)
            {
                this.age = 0;
            }
        }
    

    You can do the same with name attribute to prevent setting it to null.

        public void setName(String name)
        {
            this.name = name;
            if (name == null || name == "")
            {
                this.name = "NO NAME";
            }
        }
    

    We'll say that encapsulation help protecting data.

    ··························································································

    Now let's imagine a class called Carpenter. When you need a table, you just ask it to him. Thus the Carpenter class should provide a method which takes a description of the table you need, and return the build table. Assuming that the method is called buildTable, this method will be declared with public access because it's useful to call it from another Class.

    When you ask to the Carpenter to build up your Table, he will need to check some material as well as saw, needle and so on and so far. We (calling class) don't care about this internal mechanism and all methods as well as attributes involved in this process will be declared with private access. i.e to prevents external classes from modifying them, i.e to encapsulate our fields and methods for better protection.

    Encapsulating a field let us control access to our data.

    Comming back to your code, giving public access to getMap() doesn't prevent calling class to modify its content.

    Now look at this Example

    Person.java

    package app;
    
    /**
     *
     * @author salathielgenese
     */
    public final class Person
    {
    
        public Person()
        {
            setAge(age);
            setName(name);
        }
    
        public Person(String name, long age)
        {
            setName(name);
            setAge(age);
        }
    
        public String getName()
        {
            return name;
        }
    
        public void setName(String name)
        {
            this.name = name;
            if (name == null || name == "")
            {
                this.name = "NO NAME";
            }
        }
    
        public long getAge()
        {
            return age;
        }
    
        public void setAge(long age)
        {
            this.age = age;
            if (age < 0)
            {
                this.age = 0;
            }
        }
    
        @Override
        public String toString()
        {
            return "Person{" + "name=" + name + ", age=" + age + '}';
        }
    
        private String name;
        private long age;
    }
    

    Example.java

    package app;
    
    /**
     *
     * @author salathielgenese
     */
    public class Example
    {
    
        public Example()
        {
        }
    
        public Example(Person person)
        {
            this.person = person;
        }
    
        public Person getPerson()
        {
            return person;
        }
    
        public void setPerson(Person person)
        {
            this.person = person;
        }
    
        private Person person;
    }
    

    **Main class (Loader.java)

    package app;
    
    /**
     *
     * @author salathielgenese
     */
    public class Loader
    {
    
        /**
     * @param args the command line arguments
     */
        public static void main(String[] args)
        {
            // Instantiate an Example with a new created Person
            Example example = new Example(new Person("Rajan", 19));
            // Retrive person in example and print its description (printing result of implicit call to person.toString() )
            Person person = example.getPerson();
            System.out.println(person);
            // Assigning a new reference to the variable **person** and print its description
            person = new Person("Salathiel", 20);
            System.out.println(person);
            // Print description of Person containning in Example instance
            System.out.println(example.getPerson());
        }
    
    }
    

    If you look closed this code, you'll understand that you can change attribute of your Map but not the reference to it.