Search code examples
javaencapsulation

Class without Encapsulation


I'm having a bit of trouble understanding encapsulation in Java. What I know is that encapsulation allows for information hiding (using private variables) from anywhere else in the program. But, could anyone show me how creating a class with public data fields could cause problems? I'm not understanding how the data is hidden if the classes have getter and setter methods provided.

   public class Student{

       private int id;
       private String name;
       private int grade;

  public Student(){
  }

  public Student(int id; String name, int grade){
      this.id = id;
      this.name = name;
      this.grade = grade;
  }

  public int getId(){
       return id;
  }

  public void setId(int id){
       this.id = id;
  }

  //more code

  }

Solution

  • Here's an example where a public field can make its class completely unreliable. An alternative private version can guarantee that its information is always valid, and is untouchable by undesirable actors.

    Public field class (insecure):

    class VeryImportantCounterPublic  {
       public int currentCount;
       public VeryImportantCounterPublic(int initial_count)  {
          currentCount = initial_count;
       }
       public void incrementCount()  {
          currentCount++;
       }
       public int getCurrentCount()  {
          return  currentCount;
       }
    }
    

    Private field class (secure):

    class VeryImportantCounterPrivate  {
       private int currentCount;
       public VeryImportantCounterPrivate(int initial_count)  {
          currentCount = initial_count;
       }
       public void incrementCount()  {
          currentCount++;
       }
       public int getCurrentCount()  {
          return  currentCount;
       }
    }
    

    Main:

    public class CounterTest  {
       public static final void main(String[] ignored)  {
          VeryImportantCounterPublic counter = new VeryImportantCounterPublic(3);
          counter.incrementCount();
          counter.incrementCount();
          counter.incrementCount();
    
          //Should not be able to do this!!
          //But it's a public field, so you can  :(
          counter.currentCount = -203847382;
    
          System.out.println("[PUBLIC] Current count is " + counter.getCurrentCount());
    
    
          VeryImportantCounterPrivate counter2 = new VeryImportantCounterPrivate(3);
          counter2.incrementCount();
          counter2.incrementCount();
          counter2.incrementCount();
    
          //Can't do this. Compiler error:
          //counter2.currentCount = -203847382;
    
          System.out.println("[PRIVATE] Current count is " + counter2.getCurrentCount());
       }
    }
    

    Output:

    [PUBLIC] Current count is -203847382
    [PRIVATE] Current count is 6
    

    Full source:

    public class CounterTest  {
       public static final void main(String[] ignored)  {
          VeryImportantCounterPublic counter = new VeryImportantCounterPublic(3);
          counter.incrementCount();
          counter.incrementCount();
          counter.incrementCount();
          counter.currentCount = -203847382;
          System.out.println("[PUBLIC] Current count is " + counter.getCurrentCount());
    
    
          VeryImportantCounterPrivate counter2 = new VeryImportantCounterPrivate(3);
          counter2.incrementCount();
          counter2.incrementCount();
          counter2.incrementCount();
          //Can't do this. Compiler error:
          //counter2.currentCount = -203847382;
          System.out.println("[PRIVATE] Current count is " + counter2.getCurrentCount());
       }
    }
    
    
    class VeryImportantCounterPublic  {
       public int currentCount;
       public VeryImportantCounterPublic(int initial_count)  {
          currentCount = initial_count;
       }
       public void incrementCount()  {
          currentCount++;
       }
       public int getCurrentCount()  {
          return  currentCount;
       }
    }
    
    class VeryImportantCounterPrivate  {
       private int currentCount;
       public VeryImportantCounterPrivate(int initial_count)  {
          currentCount = initial_count;
       }
       public void incrementCount()  {
          currentCount++;
       }
       public int getCurrentCount()  {
          return  currentCount;
       }
    }