Члены класса могут использоваться с ключевым словом static. В данном контексте его значение сходно с тем, которое оно имеет в С. Когда член класса объявляется как статический, то тем самым компилятору дается указание, что должна существовать только одна копия этого члена, сколько бы объектов этого класса ни создавалось. Статический член используется совместно все­ми объектами данного класса. Все статические данные инициализируются нулями при создании первого объекта, и другая инициализация не предусмотрена.

При объявлении статического члена данных класса этот член не определяется. Вместо этого необходимо обеспечить для них глобальное определение вне класса. Это делается путем нового объявления статической переменной, причем используется оператор области видимости для того, чтобы идентифицировать тот класс, к которому принадлежит переменная. Это необходимо для того, чтобы под статическую переменную была выделена память.

В качестве примера рассмотрим следующую программу:

#include
class counter {
static int count;
public:
void setcount(int i) {count = i;};
void showcount () {cout << count << " "; }
};
int counter::count; // определение count
int main() {
counter a, b;
a.showcount (); // выводит 0
b.showcount (); // выводит 0
a.setcount (10); // установка статического count в 10
a.showcount (); // выводит 10
b.showcount (); // также выводит 10
return 0;
}

В первую очередь обратим внимание на то, что статическая переменная целого типа count объяв­ляется в двух местах: в классе counter и затем - как глобальная переменная. Borland С++ иници­ализирует count нулем. Именно поэтому первый вызов showcount() выводит в качестве результата нуль. Затем объект а устанавливает count равным 10. После этого оба объекта а и b выводят с помощью функции showcount() одну и ту же величину, равную 10. Поскольку существует только одна копия count, используемая совместно объектами а и b, то на экран выводится в обоих слу­чаях значение 10.

Также можно иметь статические функции-члены. Статические функции-члены не могут прямо ссылаться на нестатические данные или нестатические функции, объявленные в их классе. Причи­ной тому является отсутствие для них указателя this, так что нет способа узнать, с какими именно нестатическими данными работать. Например, если имеется два объекта класса, содержащие стати­ческую функцию f(), и если f() пытается получить доступ к нестатической переменной var, опреде­ленной этим классом, то как можно определить, какую именно копию var следует использовать? Компилятор не может решить такую проблему. В этом заключается причина того, что статичес­кие функции могут обращаться только к другим статическим функциям или статическим данным. Также статические функции не могут быть виртуальными или объявляться с модификаторами const иди volatile. Статическая функция может вызываться либо с использованием объекта класса, либо с использованием имени класса и оператора области видимости. Тем не менее не надо забы­вать, что даже при вызове статической функции с использованием объекта, ей не передается указатель this.

Следующая короткая программа иллюстрирует один из многих способов использования стати­ческих функций. Достаточно распространенной является ситуация, когда требуется обеспечить доступ к ограниченному ресурсу, например, такому, как совместно используемый файл в сети. Как иллюстрирует эта программа, использование статических данных и функций служит мето­дом, посредством которого объект может проверить статус ресурса и получить к нему доступ, если это возможно.

#include


class access {
static enum access_t acs;
// ...
public:


{
return acs;
}
// ...
};

int main()
{
access obj1, obj2;
access::set_access(locked); // вызов с использованием имени класса
// ... код

if (obj2.get_access()==unlocked) { // вызов с помощью объекта

cout << "Access resource.\n";
}
else cout << "Locked out.\n";
// ...
return 0;
}

При запуске этой программы на экране появится «locked out». Обратим внимание, что функция set_access() вызвана с именем класса и оператором области видимости. Функция get_access() вы­звана с объектом и оператором «точка». При вызове статической функции может использовать­ся любая из этих форм и обе они дают одинаковый эффект. Стоит поэкспериментировать немно­го с этой программой, чтобы убедиться в правильности понимания хода ее работы.

Как отмечалось, статические функции имеют прямой доступ только к другим статическим фун­кциям или статическим данным в пределах одного и того же класса. Чтобы проверить это, по­пробуем откомпилировать следующую версию программы:

// данная программа содержит ошибку и не будет компилироваться
#include
enum access_t {shared, in_use, locked, unlocked};
// класс контролирует редкий ресурс
class access {
static enum access_t acs;
int i; // не статический
// ...
public:
static void set_access (enum access_t a) {acs = a;}
static enum access_t get_access()
{
i = 100; // не будет компилироваться
return acs;
}
// ...
};
enum access_t access::acs; // определение acs
int main()
{
access obj1, obj2;
access::set_access(locked); // вызов с помощью имени класса
// ... код
// может ли obj2 обращаться к ресурсу
if(obj2.get_access()==unlocked) { // вызов с помощью объекта
access::set_access(in_use); // вызов с помощью имени класса
cout << "Access resource.\n";
}
else cout << "Locked out.\n";
// ...
}

Эта программа не будет откомпилирована, поскольку функция get_access() пытается получить доступ к нестатической переменной.

Сперва не ощущается необходимости в немедленном использовании статических членов, но по мере накопления опыта программирования на С++ они становятся очень удобным средством в определенных ситуациях, поскольку позволяют избежать использования глобальных переменных.

В этой статье мы изучим статические методы в Java и сравним Static и Instance. Главное запомнить, что если вы применяете статическое ключевое слово с любым методом, оно называется статическим методом.

Что такое статические методы в Java?

Статические методы — это методы в Java, которые можно вызывать без создания объекта класса. Они задокументированы именем {class the category}.
Статическое ключевое слово может использоваться с классом, переменной, методом и блоком. Статические члены принадлежат классу, а не конкретному экземпляру, это означает, что если вы сделаете член статическим, вы сможете получить к нему доступ без объекта. Давайте рассмотрим пример, чтобы понять это:

Здесь у нас есть статический метод myMethod(), мы можем вызвать этот метод без какого-либо объекта, потому что когда мы делаем член статическим, он становится уровнем класса. Если мы удалим ключевое слово static и сделаем его нестатичным, нам нужно будет создать объект класса для его вызова.

Статические члены являются общими для всех экземпляров (объектов) класса, но нестатические члены являются отдельными для каждого экземпляра класса.

Class SimpleStaticExample { // This is a static method static void myMethod() { System.out.println("myMethod"); } public static void main(String args) { /* You can see that we are calling this * method without creating any object. */ myMethod(); } }

Синтаксис

public static void geek(String name) { // code to be executed....

Он хранится в Permanent Generation, поскольку связывается с {class the category}, где они находятся, а не с объектами этого класса. Тем не менее, их локальные переменные, а также передаваемый им аргумент(ы) находятся в стеке.

Важные моменты:

  • Статический метод(ы), связанный с классом, в котором они находятся, то есть они будут ссылаться на него, даже если он не создает экземпляр класса, т.е. ClassName.methodName (args).
  • Они предназначены для совместного использования всеми объектами, созданными из одного класса.
  • Статические методы не могут быть переопределены.

Пример использования статических методов в Java:

Import java.io.*; class Flair{ public static String FlairName = ""; public static void geek(String name) { FlairName = name; } } class GFG { public static void main (String args) { Flair.flair("vaibhav"); System.out.println(Flair.flairName); Flair obj = new Flair (); obj.flair("shadow"); System.out.println(obj.flairName); } }

Вывод:
vaibhav
shadow

Статические переменные(static) и их значения (примитивы или ссылки) определяются внутри класса и хранятся в пространстве памяти PermGen.

Что если статическая переменная ссылается на объект?

static int i = 1;
static Object obj = new Object();

В первой строке значение, которое будет храниться в разделе PermGen. Во второй строке ссылка obj будет храниться в секции PermGen, а объект, на который она ссылается, будет храниться в секции heap.

Когда используются?

  • Если у вас есть код, который может совместно использоваться всеми экземплярами одного и того же класса, поместите эту часть кода в метод Static.
  • В первую очередь настраивайте статические поля доступа к классу.

Что такое метод экземпляра Java?

Метод экземпляра Java — это способы, которыми можно создать объект класса, прежде чем он будет вызываться. Чтобы вызвать метод экземпляра, мы должны сделать объект из категории, в которой он определен.

Public void flair(String name) // code to be {executed.... } // return type can be int, float String or user defined data type.

Параметры(переданные им аргументы), а также их локальные переменные и возвращаемое значение выделяются в стеке.

Важные моменты:

  • Инстансы принадлежат объекту класса, а не классу, т. е. они будут также ссылаться, как и после создания объекта класса.
  • Каждый отдельный объект, созданный из {класса, категории}, имеет свою собственную копию метода(ов) экземпляра этого класса.
  • Они могут быть переопределены.

Метод экземпляра или статический метод в Java?

  • Метод экземпляра получит прямой доступ к методам экземпляра и переменным.
  • Метод экземпляра будет обращаться к статическим переменным и статическим методам напрямую.
  • Статические методы будут обращаться к статическим переменным и методам напрямую.
  • Статические методы не могут напрямую обращаться к методам экземпляра и переменным экземпляра. И статический метод не может использовать это, так как нет экземпляра для «this», на который можно сослаться.

Ключевое слово static

Иногда требуется определить такой член класса, который будет использоваться независимо от всех остальных объектов этого класса. Как правило, доступ к члену класса организуется посредством объекта этого класса, но в то же время можно создать член класса для самостоятельного применения без ссылки на конкретный экземпляр объекта. Для того чтобы создать такой член класса, достаточно указать в самом начале его объявления ключевое слово static .

Если член класса объявляется как static, то он становится доступным до создания любых объектов своего класса и без ссылки на какой-нибудь объект. С помощью ключевого слова static можно объявлять как переменные, так и методы. Наиболее характерным примером члена типа static служит метод Main(), который объявляется таковым потому, что он должен вызываться операционной системой в самом начале выполняемой программы.

Для того чтобы воспользоваться членом типа static за пределами класса, достаточно указать имя этого класса с оператором-точкой. Но создавать объект для этого не нужно. В действительности член типа static оказывается доступным не по ссылке на объект, а по имени своего класса.

Переменные, объявляемые как static, по существу, являются глобальными. Когда же объекты объявляются в своем классе, то копия переменной типа static не создается. Вместо этого все экземпляры класса совместно пользуются одной и той же переменной типа static. Такая переменная инициализируется перед ее применением в классе.

Пример использования ключевого слова static:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class myCircle { // 2 метода, возвращающие площадь и длину круга public static double SqrCircle(int radius) { return Math.PI * radius * radius; } public static double LongCircle(int radius) { return 2 * Math.PI * radius; } } class Program { static void Main(string args) { int r = 10; // Вызов методов из другого класса // без создания экземпляра объекта этого класса Console.WriteLine("Площадь круга радиусом {0} = {1:#.##}",r,myCircle.SqrCircle(r)); Console.WriteLine("Длина круга равна {0:#.##}",myCircle.LongCircle(r)); Console.ReadLine(); } } }

На применение методов типа static накладывается ряд следующих ограничений:

    В методе типа static должна отсутствовать ссылка this, поскольку такой метод не выполняется относительно какого-либо объекта

    В методе типа static допускается непосредственный вызов только других методов типа static, но не метода экземпляра из того самого же класса. Дело в том, что методы экземпляра оперируют конкретными объектами, а метод типа static не вызывается для объекта. Следовательно, у такого метода отсутствуют объекты, которыми он мог бы оперировать

    Аналогичные ограничения накладываются на данные типа static. Для метода типа static непосредственно доступными оказываются только другие данные типа static, определенные в его классе. Он, в частности, не может оперировать переменной экземпляра своего класса, поскольку у него отсутствуют объекты, которыми он мог бы оперировать

Статические конструкторы

Конструктор можно также объявить как static. Статический конструктор, как правило, используется для инициализации компонентов, применяемых ко всему классу, а не к отдельному экземпляру объекта этого класса. Поэтому члены класса инициализируются статическим конструктором до создания каких-либо объектов этого класса:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class MyClass { public static int a; public int b; // Статический конструктор static MyClass() { a = 10; } // Обычный конструктор public MyClass() { b = 12; } } class Program { static void Main(string args) { Console.WriteLine("Доступ к экземпляру класса a: " + MyClass.a); MyClass obj = new MyClass(); Console.WriteLine("Доступ к экземпляру класса b: " + obj.b); Console.ReadLine(); } } }

Обратите внимание на то, что конструктор типа static вызывается автоматически, когда класс загружается впервые, причем до конструктора экземпляра. Из этого можно сделать более общий вывод: статический конструктор должен выполняться до любого конструктора экземпляра. Более того, у статических конструкторов отсутствуют модификаторы доступа - они пользуются доступом по умолчанию, а следовательно, их нельзя вызывать из программы.

Статические классы

Класс можно объявлять как static. Статический класс обладает двумя основными свойствами. Во-первых, объекты статического класса создавать нельзя . И во-вторых, статический класс должен содержать только статические члены. Статический класс создается по приведенной ниже форме объявления класса, видоизмененной с помощью ключевого слова static.

static class имя класса { // ...

Статические классы применяются главным образом в двух случаях. Во-первых, статический класс требуется при создании метода расширения . Методы расширения связаны в основном с языком LINQ. И во-вторых, статический класс служит для хранения совокупности связанных друг с другом статических методов.

Последнее обновление: 25.12.2018

Кроме обычных полей, методов, свойств класс может иметь статические поля, методы, свойства. Статические поля, методы, свойства относятся ко всему классу и для обращения к подобным членам класса необязательно создавать экземпляр класса. Например:

Class Account { public static decimal bonus = 100; public decimal totalSum; public Account(decimal sum) { totalSum = sum + bonus; } } class Program { static void Main(string args) { Console.WriteLine(Account.bonus); // 100 Account.bonus += 200; Account account1 = new Account(150); Console.WriteLine(account1.totalSum); // 450 Account account2 = new Account(1000); Console.WriteLine(account2.totalSum); // 1300 Console.ReadKey(); } }

В данном случае класс Account имеет два поля: bonus и totalSum. Поле bonus является статическим, поэтому оно хранит состояние класса в целом, а не отдельного объекта. И поэтому мы можем обращаться к этому полю по имени класса:

Console.WriteLine(Account.bonus); Account.bonus += 200;

На уровне памяти для статических полей будет создаваться участок в памяти, который будет общим для всех объектов класса.

При этом память для статических переменных выделяется даже в том случае, если не создано ни одного объекта этого класса.

Статические свойства и методы

Подобным образом мы можем создавать и использовать статические методы и свойства:

Class Account { public Account(decimal sum, decimal rate) { if (sum < MinSum) throw new Exception("Недопустимая сумма!"); Sum = sum; Rate = rate; } private static decimal minSum = 100; // минимальная допустимая сумма для всех счетов public static decimal MinSum { get { return minSum; } set { if(value>0) minSum = value; } } public decimal Sum { get; private set; } // сумма на счете public decimal Rate { get; private set; } // процентная ставка // подсчет суммы на счете через определенный период по определенной ставке public static decimal GetSum(decimal sum, decimal rate, int period) { decimal result = sum; for (int i = 1; i <= period; i++) result = result + result * rate / 100; return result; } }

Переменная minSum, свойство MinSum, а также метод GetSum здесь определены с ключевым словом static , то есть они являются статическими.

Переменная minSum и свойство MinSum представляют минимальную сумму, которая допустима для создания счета. Этот показатель не относится к какому-то конкретному счету, а относится ко всем счетам в целом. Если мы изменим этот показатель для одного счета, то он также должен измениться и для другого счета. То есть в отличии от свойств Sum и Rate, которые хранят состояние объекта, переменная minSum хранит состояние для всех объектов данного класса.

То же самое с методом GetSum - он вычисляет сумму на счете через определенный период по определенной процентной ставке для определенной начальной суммы. Вызов и результат этого метода не зависит от конкретного объекта или его состояния.

Таким образом, переменные и свойства, которые хранят состояние, общее для всех объектов класса, следует определять как статические. И также методы, которые определяют общее для всех объектов поведение, также следует объявлять как статические.

Статические члены класса являются общими для всех объектов этого класса, поэтому к ним надо обращаться по имени класса:

Следует учитывать, что статические методы могут обращаться только к статическим членам класса. Обращаться к нестатическим методам, полям, свойствам внутри статического метода мы не можем.

Нередко статические поля применяются для хранения счетчиков. Например, пусть у нас есть класс User, и мы хотим иметь счетчик, который позволял бы узнать, сколько объектов User создано:

Class User { private static int counter = 0; public User() { counter++; } public static void DisplayCounter() { Console.WriteLine($"Создано {counter} объектов User"); } } class Program { static void Main(string args) { User user1 = new User(); User user2 = new User(); User user3 = new User(); User user4 = new User(); User user5 = new User(); User.DisplayCounter(); // 5 Console.ReadKey(); } }

Статический конструктор

Кроме обычных конструкторов у класса также могут быть статические конструкторы. Статические конструкторы имеют следующие отличительные черты:

    Статические конструкторы не должны иметь модификатор доступа и не принимают параметров

    Как и в статических методах, в статических конструкторах нельзя использовать ключевое слово this для ссылки на текущий объект класса и можно обращаться только к статическим членам класса

    Статические конструкторы нельзя вызвать в программе вручную. Они выполняются автоматически при самом первом создании объекта данного класса или при первом обращении к его статическим членам (если таковые имеются)

Статические конструкторы обычно используются для инициализации статических данных, либо же выполняют действия, которые требуется выполнить только один раз

Определим статический конструктор:

Class User { static User() { Console.WriteLine("Создан первый пользователь"); } } class Program { static void Main(string args) { User user1 = new User(); // здесь сработает статический конструктор User user2 = new User(); Console.Read(); } }

Статические классы

Статические классы объявляются с модификатором static и могут содержать только статические поля, свойства и методы. Например, если бы класс Account имел бы только статические переменные, свойства и методы, то его можно было бы объявить как статический:

Static class Account { private static decimal minSum = 100; // минимальная допустимая сумма для всех счетов public static decimal MinSum { get { return minSum; } set { if(value>0) minSum = value; } } // подсчет суммы на счете через определенный период по определенной ставке public static decimal GetSum(decimal sum, decimal rate, int period) { decimal result = sum; for (int i = 1; i <= period; i++) result = result + result * rate / 100; return result; } }

В C# показательным примером статического класса является класс Math, который применяется для различных математических операций.

Последнее обновление: 08.10.2017

Кроме переменных и методов, которые относятся непосредственно к объекту, C++ позволяет определять переменные и методы, которые относятся непосредственно к классу или иначе говоя статические члены класса. Статические переменные и методы относят в целом ко всему классу. Для их определения используется ключевое слово static .

Например, в банке может быть множество различных вкладов, однако все вклады будут иметь какие-то общие процентные ставки. Так, для описания банковского счета определим и используем следующий класс:

#include class Account { public: Account(double sum) { this->sum = sum; } static int getRate() { return rate; } static void setRate(int r) { rate = r; } double getIncome() { return sum + sum * rate / 100; } private: double sum; static int rate; }; int Account::rate = 8; int main() { Account account1(20000); Account account2(50000); Account::setRate(5); // переустанавливаем значение rate std::cout << "Rate: " << Account::getRate() << std::endl; std::cout << "Rate: " << account1.getRate() << " Income: " << account1.getIncome() << std::endl; std::cout << "Rate: " << account2.getRate() << " Income: " << account2.getIncome() << std::endl; return 0; }

В классе Account определена одна статическая переменная rate и две статических функции для управления этой переменной. При определении статических функций стоит учитывать, что внутри них мы можем использовать только статические переменные класса, как например, переменную rate. Нестатические переменные использовать в статических функциях нельзя.

Кроме того, в статических функциях нельзя использовать указатель this, что в принципе и так очевидно, так как this указывает на текущий объект, а статические функции относятся вцелом ко всему классу.

Также важно, что если класс содержит статические переменные, то они должны быть дополнительно определены вне класса:

Int Account::rate = 8;

Присваивать начальное значение переменной необязательно.

Также стоит отметить, что так как статические члены относятся в целом ко всему классу, то для обращения к статическим членам используется имя класса, после которого идет оператор :: . Либо мы можем также обращаться к публичным членам класса через переменные данного класса:

Account::getRate() account1.getRate()

Консольный вывод программы:

Rate: 5 Rate: 5 Income: 21000 Rate: 5 Income: 52500

Также нередко в классах используют статические константы. Например, сделаем в классе Account переменную rate константой:

#include class Account { public: const static int rate = 8; Account(double sum) { this->sum = sum; } double getIncome() { return sum + sum * rate / 100; } private: double sum; }; int main() { Account account1(20000); Account account2(50000); std::cout << "Rate: " << account1.rate << "\tIncome: " << account1.getIncome() << std::endl; std::cout << "Rate: " << account2.rate << "\tIncome: " << account2.getIncome() << std::endl; return 0; }

В отличие от статических переменных статические константы не нужно дополнительно определять вне класса.


Close