Understanding Class Members
In this section, we discuss the use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class.
Class Variables
When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables. In the case of the Bicycle class, the instance variables are cadence , gear , and speed . Each Bicycle object has its own values for these variables, stored in different memory locations.
Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.
For example, suppose you want to create a number of Bicycle objects and assign each a serial number, beginning with 1 for the first object. This ID number is unique to each object and is therefore an instance variable. At the same time, you need a field to keep track of how many Bicycle objects have been created so that you know what ID to assign to the next one. Such a field is not related to any individual object, but to the class as a whole. For this you need a class variable, numberOfBicycles , as follows:
Class variables are referenced by the class name itself, as in
This makes it clear that they are class variables.
You can use the Bicycle constructor to set the id instance variable and increment the numberOfBicycles class variable:
public class Bicycle < private int cadence; private int gear; private int speed; private int id; private static int numberOfBicycles = 0; public Bicycle(int startCadence, int startSpeed, int startGear)< gear = startGear; cadence = startCadence; speed = startSpeed; // increment number of Bicycles // and assign ID number id = ++numberOfBicycles; > // new method to return the ID instance variable public int getID() < return id; >. >
Class Methods
The Java programming language supports static methods as well as static variables. Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in
instanceName.methodName(args)
A common use for static methods is to access static fields. For example, we could add a static method to the Bicycle class to access the numberOfBicycles static field:
public static int getNumberOfBicycles()
Not all combinations of instance and class variables and methods are allowed:
- Instance methods can access instance variables and instance methods directly.
- Instance methods can access class variables and class methods directly.
- Class methods can access class variables and class methods directly.
- Class methods cannot access instance variables or instance methods directlythey must use an object reference. Also, class methods cannot use the this keyword as there is no instance for this to refer to.
Constants
The static modifier, in combination with the final modifier, is also used to define constants. The final modifier indicates that the value of this field cannot change.
For example, the following variable declaration defines a constant named PI , whose value is an approximation of pi (the ratio of the circumference of a circle to its diameter):
static final double PI = 3.141592653589793;
Constants defined in this way cannot be reassigned, and it is a compile-time error if your program tries to do so. By convention, the names of constant values are spelled in uppercase letters. If the name is composed of more than one word, the words are separated by an underscore (_).
Note: If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.
The Bicycle Class
After all the modifications made in this section, the Bicycle class is now:
public class Bicycle < private int cadence; private int gear; private int speed; private int id; private static int numberOfBicycles = 0; public Bicycle(int startCadence, int startSpeed, int startGear) < gear = startGear; cadence = startCadence; speed = startSpeed; >public int getID() < return id; >public static int getNumberOfBicycles() < return numberOfBicycles; >public int getCadence() < return cadence; >public void setCadence(int newValue) < cadence = newValue; >public int getGear() < return gear; >public void setGear(int newValue) < gear = newValue; >public int getSpeed() < return speed; >public void applyBrake(int decrement) < speed -= decrement; >public void speedUp(int increment) < speed += increment; >>
10 заметок о модификаторе Static в Java
Модификатор static в Java напрямую связан с классом. Если поле статично, значит оно принадлежит классу, если метод статичный — аналогично: он принадлежит классу. Исходя из этого, можно обращаться к статическому методу или полю, используя имя класса. Например, если поле count статично в классе Counter, значит, вы можете обратиться к переменной запросом вида: Counter.count. Прежде чем приступить к заметкам, давайте вспомним (а может быть, узнаем), что такое static и что может быть статическим в Java. Static — модификатор, применяемый к полю, блоку, методу или внутреннему классу. Данный модификатор указывает на привязку субъекта к текущему классу.
Статические поля
При обозначении переменной уровня класса мы указываем на то, что это значение относится к классу. Если этого не делать, то значение переменной будет привязываться к объекту, созданному по этому классу. Что это значит? А то, что если переменная не статическая, то у каждого нового объекта данного класса будет своё значение этой переменной, меняя которое мы меняем его исключительно в одном объекте: Например, у нас есть класс Car с нестатической переменной:
Car orangeCar = new Car(); orangeCar.km = 100; Car blueCar = new Car(); blueCar.km = 85; System.out.println("Orange car - " + orangeCar.km); System.out.println("Blue car - " + blueCar.km);
Orange car - 100 Blue car - 85
Как видим, у каждого объекта своя переменная, изменение которой происходит только для этого объекта. Ну а если у нас переменная статическая, то это глобальное значение — одно для всех: Теперь мы имеем Car со статической переменной:
Orange car - 85 Blue car - 85
Ведь переменная у нас одна на всех, и каждый раз мы меняем именно ее. К статическим переменным, как правило обращаются не по ссылке на объект — orangeCar.km, а по имени класса — Car.km
Статический блок
Есть два блока инициализации — обычный и статический. Блок предназначен для инициализации внутренних переменных. Если блок обычный, то им инициализируют внутренние переменные объекта, если же статический, соответственно, им задают статические переменные (то есть переменные класса). Пример класса со статическим блоком инициализации:
Статический метод
Статические методы отличаются от обычных тем, что они также привязаны к классу, а не к объекту. Важным свойством статического метода является то, что он может обратиться только к статическим переменным/методам. В качестве примера давайте рассмотрим класс, который у нас будет неким счётчиком, ведущим учет вызовов метода:
Counter.invokeCounter(); Counter.invokeCounter(); Counter.invokeCounter();
Текущее значение счётчика - 1 Текущее значение счётчика - 2 Текущее значение счётчика - 3
Статический класс в Java
Статическим классом может быть только внутренний класс. Опять же, этот класс привязан к внешнему классу, и если внешний наследуется другим классом, то этот не будет наследован. При этом данный класс можно наследовать, как и он может наследоваться от любого другого класса и имплементировать интерфейс. По сути статический вложенный класс ничем не отличается от любого другого внутреннего класса за исключением того, что его объект не содержит ссылку на создавший его объект внешнего класса. Тем не менее, благодаря этому статический класс наиболее похож на обычный не вложенный, ведь единственное различие состоит в том, что он упакован в другой класс. В некоторых случаях для нас это преимущество, так как с него у нас есть доступ к приватным статическим переменным внешнего класса. Пример вложенного статического класса:
Vehicle.Car car = new Vehicle.Car(); car.km = 90;
Для использования статических методов/переменных/класса нам не нужно создавать объект данного класса. Конечно, следует учитывать модификаторы доступа. Например, поля private доступны только внутри класса, в котором они объявлены. Поля protected доступны всем классам внутри пакета (package), а также всем классам-наследникам вне пакета. Для более подробной информации ознакомьтесь со статьей “private vs protected vs public”. Предположим, существует статический метод increment() в классе Counter , задачей которого является инкрементирование счётчика count . Для вызова данного метода можно использовать обращение вида Counter.increment() . Нет необходимости создавать экземпляр класса Counter для доступа к статическому полю или методу. Это фундаментальное отличие между статическими и НЕ статическими объектами (членами класса). Еще раз напомню, что статические члены класса напрямую принадлежат классу, а не его экземпляру. То есть, значение статической переменной count будет одинаковое для всех объектов типа Counter . Далее в этой статье мы рассмотрим основополагающие аспекты применения модификатора static в Java, а также некоторые особенности, которые помогут понять ключевые концепции программирования.
Что должен знать каждый программист о модификаторе Static в Java
- Вы НЕ можете получить доступ к НЕ статическим членам класса, внутри статического контекста, как вариант, метода или блока. Результатом компиляции приведенного ниже кода будет ошибка:
class Vehicle < public static void kmToMiles(int km)< System.out.println("Внутри родительского класса/статического метода"); >> class Car extends Vehicle < public static void kmToMiles(int km)< System.out.println("Внутри дочернего класса/статического метода "); >> public class Demo< public static void main(String args[])< Vehicle v = new Car(); v.kmToMiles(10); >>