Лучше один раз увидеть, чем сто раз услышать!

public править

Доступен всем!

Пример определения публичных элементов:

class A {
  public int m;
  public void f() {
  }
  public static String name = "Test";
}

Теперь посмотрим как этим пользуются:

class B {
  void someFunction(){
    String myString = A.name; //К публичным статическим членам можно обращаться даже не имея экземпляра
    A a = new A(); //Создаем экземпляр
    a.m = 10; //Доступ к публичному целому члену в точности такой же как к обычной целой переменной
    a.m++; 
    a.f(); //Функция также доступна из любого места
  }
}

protected править

Доступен внутри пакета и своим подклассам из других пакетов.

class A {
  protected int x;
  protected void f() {}
  protected static String name = "Ku-Ku";
}

class B extends A {
  public void someFunc() {
    x = 10; //Доступ к защищённому члену родительского класса
    f(); 
    A ref = new A();
    ref.x = 13; //В контексте дочернего класса обращение к защищённым членам ЗАПРЕЩЕНО (приведет к ошибке компиляции)
    String bebe = A.name; //Статические переменные - не исключение
  }
}

class C {
  public void someFunc() {
    String mmm = A.name; //Неверный вызов. Переменная name - защищена и не видна извне (Только если класс С находится в другом пакете. Если класс С находится в том же пакете, что и А, то переменная name будет доступна)
    A a = new A();
    int myX = a.x; //Неверный вызов. Переменная x - не видна извне (Только если класс С находится в другом пакете. Если класс С находится в том же пакете, что и А, то переменная х будет доступна)
    a.x = 1; //Неверный вызов. Переменная x - не видна извне (Только если класс С находится в другом пакете. Если класс С находится в том же пакете, что и А, то переменная х будет доступна)
    a.f(); //Неверный вызов. Функция f - не видна извне (Только если класс С находится в другом пакете. Если класс С находится в том же пакете, что и А, то функция f будет доступна)
  }
}

package-private править

Доступен в пределах своего пакета package. Присваивается автоматически, если не указан модификатор доступа.

class A { //Этот класс виден только в пакете, в котором находится сам
  int x;  //Члены класса видны для всех классов данного пакета
}

private править

Доступен только внутри своего класса.

class A {
  private int x; //переменную x видно исключительно внутри класса A

  public void setX(int value) { //обычно такую функцию называют "setter"
    x = value;
  }

  public int getX() { //обычно такую функцию называют "getter"
    return x;
  }
}

class B extends A {
  public void someFunc() {
    this.x = 10; //Ошибка! Приватные переменные не видны даже наследникам
  }
}

setX и getX - являются функциями доступа к приватной переменной. Если мы решим, что переменная x может содержать исключительно числа от 1 до 100, то нам не понадобится искать все обращения к x по всем классам, а просто добавить проверку между строками  N и  N.