How many access levels does Java have anyway?

Before I start with my new post, I would like to talk a little about my previous one: "Rule for public void method signatures". As it turns out, this is a proposal for Java 7 called "chained invocations". You can find more details here. There is also another way of doing this called "Double Brace Initialization":

JPanel panel = new JPanel() {{
  setLayout(new BorderLayout());
  setBorder(BorderFactory.createEmptyBorder());
}};

At first site, it seems useful in a number of situations (i.e. Graphical User Interfaces), on the other hand, many suggest that this should not be abused as it creates ugly and cluttered code.

Now, let's put that in the side and go back to what you have learned in Java programming.

You've learned that one of the most basic techniques of Object Oriented programming is encapsulation (a.k.a. information hiding). How do you properly use this technique? Well, you start by defining all your members private. Only if necessary you will go protected (or package protected) and, only when absolutely necessary, you go public. In most cases you provide accessors and mutators to allow classes to manipulate these members from outside.

class Person {
  private String name;
  private int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return this.name;
  }

  public int getAge() {
    return this.age;
  }
}

Of course, along with the toString method, you will usually want to override the equals method as well:

public boolean equals(Object obj) {
  if (this == obj)
    return true;
  if (obj == null)
    return false;
  if (getClass() != obj.getClass())
    return false;
  Person other = (Person) obj;
  if (age != other.getAge())
    return false;
  if (name == null) {
    if (other.getName() != null)
      return false;
  } else if (!name.equals(other.getName()))
    return false;
  return true;
}

So, everything looks good and you go on with your life, learning more and more about Java, until one day you come across this article about getters and setters being evil and all. Assuming you agree with it (personally I find it unnecessary in many cases), the first thing you do is wipe out the getters and provide alternatives. For example (OK, for Person, this might look to much but bare with me):

class Person {
  private String name;
  private int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public void displayName(Displayer d) {
    d.display(this.name);
  }

  public void displayAge(Displayer d) {
    d.display(this.age);
  }

  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Person other = (Person) obj;
    if (age != other.getAge())
      return false;
    if (name == null) {
      if (other.getName() != null)
        return false;
    } else if (!name.equals(other.getName()))
      return false;
    return true;
  }
}

But wait.... There is no accessor for the name and age anymore. How am I going to compare these two now? Oh well.. Back to the getters again. But wait! There's more! Let me remind you what you read the first time:

"Access level modifiers determine whether other CLASSES can use a particular field or invoke a particular method."

So, this basically says:

public boolean equals(Object obj) {
  if (this == obj)
    return true;
  if (obj == null)
    return false;
  if (getClass() != obj.getClass())
    return false;
  Person other = (Person) obj;
  if (age != other.age)
    return false;
  if (name == null) {
    if (other.name != null)
      return false;
  } else if (!name.equals(other.name))
    return false;
  return true;
}

Didn't like the example? I agree, I didn't either. Let's make a much much simpler one:

class MyClass {
  private int privateInt;	

  private int getEvil() {
    return 666;
  }

  public void violateEncapsulation(MyClass e) {
    e.privateInt = e.getEvil();
  }
}

"Wai..Wha..Whe..Fu..?" is exactly how I reacted the first time. Is there another access level I should know of? Is there a...weird private? How could I have known? Was I sleeping in class?

Well, for one, yes, but then again, it's the first line at the Java tutorial. The only problem with this is that there is no example anywhere. So even if you read it, you'd probably ignore it. Furthermore, you'll rarely find it elsewhere too. Until, one day, you use eclipse to generate an equals method (which was my case). Other places you will probably "spot" this is in the equals method, or the clone method or any copy methods.

Still, it could get ugly...

class Sloppy {
  private int value;

  public static void justSetIt(Sloppy s, int val) {
    s.value = val;
  }
}