Сегодня, как и обещалось в статье о пакетах, мы поговорим о модификаторах: какие бывают модификаторы, области видимости, модификаторы для классов, полей, методов. Думаю, будет не скучно.
Модификаторы в Java – это ключевые слова, которые придают классу, полю класса или методу определенные свойства.
Для обозначения видимости класса его методов и полей есть 4 модификатора доступа:
- private члены класса доступны только внутри класса;
- package-private или default (по умолчанию) члены класса видны внутри пакета;
- protected члены класса доступны внутри пакета и в классах-наследниках;
- public члены класса доступны всем.
Если Вы помните прошлую статью, то в конце, когда мы уже импортировали класс Cat, у нас все равно была ошибка компиляции.
public class Cat {
String color;
int weight;
String sex;
char s;
double v;
float g;
boolean b;
Cat() {//конструктор без параметров
//сюда можно писать код, который будет выполняться при создании объекта
}
Cat(String catsColor){//конструктор с одним параметром
color = catsColor;
}
Cat(String catsColor, int catsWeight, String catsSex){//конструктор с тремя параметрами
color = catsColor;
weight = catsWeight;
sex = catsSex;
}
void myaukat(int count){
for (int i = 0; i < count; i++) {
System.out.println("Meaou!");
}
}
void walk(){
System.out.println("Char " + s);
System.out.println(v);
System.out.println(g);
System.out.println(b);
}
String methodForEveryObject(){
return color + " cat is walking";
}
}
Все дело в том, что мы не прописали никаких модификаторов доступа к нашим полям и методам и они имеют свойство по умолчанию (члены класса видны внутри пакета). Чтобы исправить ошибку компиляции для нашего кода и наконец то запустить его, нужно сделать наш конструктор и методы public. Тогда их можно будет вызывать с других пакетов.
Вы можете начать задаваться вопросом: а для чего все это нужно? Почему не сделать видимость кода из любого пакета или класса, а нужно разграничить доступ? Эти вопросы сами пропадут, когда придет время писать сложные и громоздкие проекты. Сейчас, когда мы пишем приложения, у которых функционал ограничен одним или двумя классами, то смысла что либо ограничить вроде как не видно.
Представьте, что у Вас есть класс который отображает объект некоего продукта. Например машина. У машины может быть цена. Вы создали поле цена и еще множество других полей, кучу методов которые отвечают за функционал. Все вроде хорошо. Ваш класс машина является частью огромного проекта и все довольны. Но допустим, что кто-то по ошибке или специально создал экземпляр класса автомобиль и поставил отрицательную цену. Разве может товар иметь отрицательную цену? Это очень примитивный пример и вряд ли такое может случиться в реальной жизни, но думаю, идея понятна. Иногда нужно дать доступ не напрямую, а через определенные методы. Может быть, что код отвечает за функционал другого кода, и Вы не хотите, чтобы кто-то изменял и редактировал часть Вашего. Для этого всего и есть ограничение доступа.
Модификатор доступа у конструкторов, методов и полей может быть любой. Класс может быть только либо public, либо default, причем в одном файле может находиться только один public класс.
Пока об модификаторах доступа будет достаточно. В статье “Объектно ориентированное программирование” мы о них поговорим подробнее, а сейчас давайте поговорим о других модификаторах которых, к стати, немало.
Сейчас на очереди модификатор static. Его можно применять перед методом, полем и даже классом, когда хотим объявить вложенный класс. В Java можно писать классы внутри других классов и если модификатор перед классом внутри класса static, то такой класс называют вложенным, если другой модификатор или по умолчанию, то такой класс называется внутренним. О вложенных и внутренних классах будет отдельная статья, поскольку там не все так просто.
static модификатор перед методом или полем говорит о том, что они не принадлежат к экземпляру данного класса. Что это означает для нас? Когда мы описали поле класса или метод как static, его можно вызвать без использования экземпляра класса. То есть вместо такой конструкции: Cat cat = new Cat(); cat.method(), можно написать просто Cat.method(). При условии, что метод объявлен как static. Статические переменные едины для всех объектов класса. У них одна ссылка.
static String someField;
static int anotherStaticField = 5;
String nonStaticField;
public static void myStaticMethod(){
someField = "My field";
//nonStaticField = ""; ошибка компиляции
//нельзя использовать нестатические поля
//в статических методах
}
public void myNonStaticMethod(){
anotherStaticField = 4;//ститические поля можно использовать
//в нестатических методах
}
public static void main(String[] args){//обратите внимание,
//main метод тоже имеет модификатор static
System.out.println(Modificators.anotherStaticField);//5
new Modificators().myNonStaticMethod();
System.out.println(Modificators.anotherStaticField);//4
Modificators.myStaticMethod();//вызов статических методов и полей
//через имяКласса.метод
}
}
Еще одно важное замечание, которое нужно сказать по поводу static модификаторов: статические поля инициализируются во время загрузки класса. Часто в разного рода тестах по Java можно встретить такой код:
{
System.out.println(1);
}
static {
System.out.println(2);
}
public OftenQuestions() {
System.out.println(3);
}
public void myMethod(){
System.out.println(4);
}
public static void main(String[] args) {
System.out.println(5);
OftenQuestions o = new OftenQuestions();
o.myMethod();
}
}
Вопрос: что будет выведено на консоль? Нужно помнить, что static блок будет выведен первым при любом раскладе. Далее будет идти блок по умолчанию. Далее смотрите на скрин консоли:
Следующий модификатор, который мы рассмотрим будет final.
Думаю, слово final говорит само за себя. Применяя final модификатор Вы говорите, что поля не могут быть изменены, методы переопределены, а классы нельзя наследовать (о наследовании будет отдельная статья). Этот модификатор применяется только к классам, методам и переменным (также и к локальным переменным).
final static String CONSTANT = "Hi there";//полю CONSTANT нельзя дать новое значение
//таким образом в джаве можно объявлять константы.
//константы в языке Java обычно пишут в верхнем регистре
final int ANOTHER_CONSTANT;
//константы нужно инициализировать при объявлении или в конструкторе.
public static void main(String[] args) {
// TODO Auto-generated method stub
FinalModificator.CONSTANT = "Bue there";//ошибка компиляции
//попытка переопределить константу
}
}
С модификатором final к методам и классам мы будем говорить в статье ООП.
Далее пойдут модификаторы, которые новичкам или читающим данный цикл статей с нуля будут не очень понятными. И хотя я пока не смогу Вам все объяснить (в силу того, что Вы не знаете сопутствующего материала), все же советую просто ознакомиться с ними. Когда придет время использования данных модификаторов, Вы уже будете понимать большинство терминов используемых ниже.
Модификатор synchronized – говорит о том, что метод может быть использован только одним потоком одновременно. Хотя, возможно, это Вам ни о чем не говорит, полезность этого модификатора будет видно, когда мы будем изучать многопоточность.
Модификатор transient – говорит о том, что во время сериализации объекта некоторое поле нужно игнорировать. Как правило, такие поля хранят промежуточные значения.
Модификатор volatile – используется при многопоточности. Когда поле с модификатором volatile будет использоваться и изменяться несколькими потоками, данный модификатор гарантирует, что поле будет изменяться по очереди и путаницы с ним не возникнет.
Модификатор native перед объявлением метода указывает что метод написан на другом языке программирования. Обычно на языке C.
Модификатор strictfp – Обеспечивает выполнение операций над числами типа float и double (с плавающей запятой) по стандарту IEEE 754. Или говоря проще, гарантирует что в пределах метода результаты вычислений будут одинаковыми на всех платформах.
Я еще не говорил о модификаторе abstract. О нем скажу вкратце, так как без знаний основ объектно ориентированного программирования говорить о нем не вижу смысла.
Класс, который имеет модификатор abstract не может создать экземпляр. Единственная цель для него быть расширенным. Класс abstract может содержать как абстрактные методы, а также и обычные.
Подробнее о модификаторе abstract будем говорить в статье ООП.
На этом можно и закончить статью о модификаторах. Многое о них не было сказано. Но это из-за того, что у нас еще нет понятий ООП. Через несколько статей, мы дополним знания о модификаторах и заполним пробелы.
Ошибка, если инициализатор static, то и класс должен быть static – P.S. мне ругнулась IDE