Что делает ключевое слово static в классе?
Чтобы быть конкретным, я пытался этот код:
package hello;
public class Hello {
Clock clock = new Clock();
public static void main(String args[]) {
clock.sayTime();
}
}
Но это дало ошибку
Невозможно получить доступ к нестатическому полю в статическом методе main
Поэтому я изменил декларацию clock
к этому:
static Clock clock = new Clock();
И это сработало. Что значит поставить это ключевое слово перед объявлением? Что именно он будет делать и / или ограничивать с точки зрения того, что можно сделать с этим объектом?
23 ответа
static
члены принадлежат классу, а не конкретному экземпляру.
Это означает, что только один экземпляр static
поле существует [1], даже если вы создаете миллион экземпляров класса или не создаете ни одного. Он будет доступен всем экземплярам.
поскольку static
методы также не принадлежат конкретному экземпляру, они не могут ссылаться на члены экземпляра. В приведенном примере main
не знает, какой экземпляр Hello
класс (и, следовательно, какой экземпляр Clock
класс) это должно относиться к. static
участники могут ссылаться только на static
члены. Члены экземпляра могут, конечно, получить доступ static
члены.
Примечание: конечно, static
члены могут получить доступ к членам экземпляра через ссылку на объект.
Пример:
public class Example {
private static boolean staticField;
private boolean instanceField;
public static void main(String[] args) {
// a static method can access static fields
staticField = true;
// a static method can access instance fields through an object reference
Example instance = new Example();
instance.instanceField = true;
}
[1]: В зависимости от характеристик времени выполнения, это может быть один для ClassLoader или AppDomain или потока, но это не относится к делу.
Это означает, что в Hello существует только один экземпляр "clock", а не по одному на каждый отдельный экземпляр класса "Hello", или, более того, это означает, что среди всех экземпляров будет одна общедоступная ссылка "clock". класс "Привет".
Таким образом, если бы вы выполняли "новый Hello" где-нибудь в вашем коде: A- в первом сценарии (до изменения, без использования "static"), он делал бы новые часы каждый раз, когда вызывается "new Hello", но B- во втором сценарии (после изменения, используя "static"), каждый "новый Hello" экземпляр все равно будет совместно использовать и использовать начальную и ту же самую ссылку "clock", которая была впервые создана.
Если вам не нужны "часы" где-то за пределами основного, это будет работать так же хорошо:
package hello;
public class Hello
{
public static void main(String args[])
{
Clock clock=new Clock();
clock.sayTime();
}
}
static
Ключевое слово означает, что что-то (поле, метод или вложенный класс) относится к типу, а не к какому-либо конкретному экземпляру типа. Так, например, один звонит Math.sin(...)
без какого-либо экземпляра Math
класс, и на самом деле вы не можете создать экземпляр Math
учебный класс.
Для получения дополнительной информации см. Соответствующий раздел Oracle Java Tutorial.
Примечание
К сожалению, Java позволяет вам получать доступ к статическим членам, как если бы они были членами экземпляра, например
// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);
Это выглядит так, как будто sleep
это метод экземпляра, но на самом деле это статический метод - он всегда заставляет текущий поток спать. Лучше прояснить это в вызывающем коде:
// Clearer
Thread.sleep(5000);
static
Ключевое слово в Java означает, что переменная или функция являются общими для всех экземпляров этого класса, поскольку они принадлежат типу, а не самим фактическим объектам.
Так что если у вас есть переменная: private static int i = 0;
и вы увеличиваете его (i++
) в одном случае изменение будет отражено во всех случаях. i
теперь будет 1 во всех случаях.
Статические методы могут использоваться без создания объекта.
Основное использование статических членов...
public class Hello
{
// value / method
public static String staticValue;
public String nonStaticValue;
}
class A
{
Hello hello = new Hello();
hello.staticValue = "abc";
hello.nonStaticValue = "xyz";
}
class B
{
Hello hello2 = new Hello(); // here staticValue = "abc"
hello2.staticValue; // will have value of "abc"
hello2.nonStaticValue; // will have value of null
}
Таким образом, вы можете иметь общие значения для всех членов класса, не отправляя экземпляр класса Hello другому классу. И, кроме статики, вам не нужно создавать экземпляр класса.
Hello hello = new Hello();
hello.staticValue = "abc";
Вы можете просто вызывать статические значения или методы по имени класса:
Hello.staticValue = "abc";
Статический означает, что вам не нужно создавать экземпляр класса, чтобы использовать методы или переменные, связанные с классом. В вашем примере вы могли бы позвонить:
Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class
напрямую, а не:
Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable
Внутри статического метода (который принадлежит классу) вы не можете получить доступ к любым элементам, которые не являются статическими, так как их значения зависят от вашего экземпляра класса. Нестатический объект Clock, являющийся членом экземпляра, будет иметь разные значения / ссылки для каждого экземпляра вашего класса Hello, и поэтому вы не сможете получить к нему доступ из статической части класса.
Статика в Java:
Static - это не модификатор доступа. Ключевое слово static относится к классу, а не к экземпляру класса. может использоваться для присоединения переменной или метода к классу.
Статическое ключевое слово МОЖЕТ использоваться с:
метод
переменная
Класс, вложенный в другой класс
Блок инициализации
НЕ МОЖЕТ использоваться с:
Класс (не вложенный)
Конструктор
Интерфейсы
Метод Local Inner Class(отличие от вложенного класса)
Методы внутреннего класса
Переменные экземпляра
Локальные переменные
Пример:
Представьте себе следующий пример, в котором есть переменная экземпляра с именем count, которая увеличивается в конструкторе:
package pkg;
class StaticExample {
int count = 0;// will get memory when instance is created
StaticExample() {
count++;
System.out.println(count);
}
public static void main(String args[]) {
StaticExample c1 = new StaticExample();
StaticExample c2 = new StaticExample();
StaticExample c3 = new StaticExample();
}
}
Выход:
1 1 1
Поскольку переменная экземпляра получает память во время создания объекта, у каждого объекта будет копия переменной экземпляра, и если она увеличивается, она не будет отражаться для других объектов.
Теперь, если мы изменим значение переменной экземпляра на статическое, тогда программа выдаст другой результат:
package pkg;
class StaticExample {
static int count = 0;// will get memory when instance is created
StaticExample() {
count++;
System.out.println(count);
}
public static void main(String args[]) {
StaticExample c1 = new StaticExample();
StaticExample c2 = new StaticExample();
StaticExample c3 = new StaticExample();
}
}
Выход:
1 2 3
В этом случае статическая переменная получит память только один раз, если какой-либо объект изменит значение статической переменной, он сохранит свое значение.
Статический с финалом:
Глобальная переменная, объявленная как final и static, остается неизменной на протяжении всего выполнения. Потому что статические члены хранятся в памяти классов и загружаются только один раз за все выполнение. Они являются общими для всех объектов класса. Если вы объявите статические переменные как окончательные, ни один из объектов не сможет изменить их значение, поскольку оно является окончательным. Поэтому переменные, объявленные как final и static, иногда называют константами. Все поля интерфейсов называются константами, потому что они являются окончательными и статическими по умолчанию.
Ресурс изображения: Final Static
Чтобы добавить к существующим ответам, позвольте мне попробовать с изображением:
Процентная ставка 2% применяется ко ВСЕМ сберегательным счетам. Следовательно, это статично.
Баланс должен быть индивидуальным, чтобы он не был статичным.
Это обсуждение до сих пор игнорировало соображения загрузчика классов. Строго говоря, статические поля Java совместно используются всеми экземплярами класса для данного загрузчика классов.
Поле может быть назначено либо классу, либо экземпляру класса. По умолчанию поля являются переменными экземпляра. Используя static
поле становится переменной класса, таким образом, есть один и только один clock
, Если вы вносите изменения в одном месте, это видно везде. Varables экземпляра изменяются независимо друг от друга.
Ключевое слово static
используется для обозначения поля или метода как принадлежащих самому классу, а не экземпляру. Используя ваш код, если объект Clock
статичен, все экземпляры Hello
класс поделится этим Clock
элемент данных (поле) общий. Если вы сделаете его нестатичным, каждый отдельный экземпляр Hello
может иметь уникальный Clock
поле.
Проблема в том, что вы добавили метод main в ваш класс Hello
чтобы вы могли запустить код. Проблема здесь заключается в том, что основной метод является статическим и поэтому не может ссылаться на нестатические поля или методы внутри него. Вы можете решить это двумя способами:
- Сделайте все поля и методы
Hello
Класс static, чтобы на них можно было ссылаться внутри метода main. Это действительно не очень хорошая вещь (или неправильная причина, по которой поле и / или метод становятся статическими) - Создайте экземпляр своего
Hello
Класс внутри метода main и доступ ко всем его полям и методам так, как они были предназначены в первую очередь.
Для вас это означает следующее изменение вашего кода:
package hello;
public class Hello {
private Clock clock = new Clock();
public Clock getClock() {
return clock;
}
public static void main(String args[]) {
Hello hello = new Hello();
hello.getClock().sayTime();
}
}
На Яве static
Ключевое слово можно просто рассматривать как указывающее на следующее:
"безотносительно к любому конкретному случаю"
Если вы думаете о static
таким образом, становится легче понять его использование в различных контекстах, в которых оно встречается:
static
поле - это поле, которое принадлежит классу, а не какому-либо конкретному экземпляруstatic
Метод это метод, который не имеет понятияthis
; он определен в классе и не знает ни о каком конкретном экземпляре этого класса, если на него не передана ссылкаstatic
класс-член является вложенным классом без какого-либо представления или знания экземпляра его включающего класса (если только ему не передана ссылка на экземпляр включающего класса)
Статические методы не используют переменные экземпляра класса, в котором они определены. Очень хорошее объяснение различий можно найти на этой странице
Я разработал привязку к статическим методам (только, если это возможно) в "вспомогательных" классах.
Вызывающему классу не нужно создавать другую переменную-член (экземпляр) вспомогательного класса. Вы просто вызываете методы вспомогательного класса. Также улучшен вспомогательный класс, потому что вам больше не нужен конструктор и вам не нужны переменные-члены (экземпляры).
Есть, вероятно, другие преимущества.
Static делает член часов членом класса вместо члена экземпляра. Без статического ключевого слова вам потребуется создать экземпляр класса Hello (который имеет переменную-член clock) - например,
Hello hello = new Hello();
hello.clock.sayTime();
//Here is an example
public class StaticClass
{
static int version;
public void printVersion() {
System.out.println(version);
}
}
public class MainClass
{
public static void main(String args[]) {
StaticClass staticVar1 = new StaticClass();
staticVar1.version = 10;
staticVar1.printVersion() // Output 10
StaticClass staticVar2 = new StaticClass();
staticVar2.printVersion() // Output 10
staticVar2.version = 20;
staticVar2.printVersion() // Output 20
staticVar1.printVersion() // Output 20
}
}
Понимание статических концепций
public class StaticPractise1 {
public static void main(String[] args) {
StaticPractise2 staticPractise2 = new StaticPractise2();
staticPractise2.printUddhav(); //true
StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */
StaticPractise2.printUddhavsStatic1(); //true
staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static things and it organizes in its own heap. So, class static methods, object can't reference */
}
}
Второй класс
public class StaticPractise2 {
public static void printUddhavsStatic1() {
System.out.println("Uddhav");
}
public void printUddhav() {
System.out.println("Uddhav");
}
}
Также можно думать о статических членах, не имеющих указателя "this". Они распределяются между всеми экземплярами.
main()
статический метод, имеющий два основных ограничения:
- Статический метод не может использовать нестатический элемент данных или напрямую вызывать нестатический метод.
this()
а такжеsuper()
не может использоваться в статическом контексте.class A { int a = 40; //non static public static void main(String args[]) { System.out.println(a); } }
Вывод: ошибка времени компиляции
Был задан вопрос здесь о выборе слова "статический" для этой концепции. Ответ на этот вопрос был обманут, но я не думаю, что этимология ясно рассмотрена. Так...
Это связано с повторным использованием ключевых слов, начиная с C.
Рассмотрим объявления данных в C (внутри тела функции):
void f() {
int foo = 1;
static int bar = 2;
:
}
Переменная foo создается в стеке при входе в функцию (и уничтожается при завершении функции). Напротив, бар присутствует всегда, поэтому он "статичен" в смысле обычного английского языка - он никуда не денется.
В Java и подобных языках используется та же концепция данных. Данные могут быть выделены для каждого экземпляра класса (для каждого объекта) или один раз для всего класса. Поскольку Java стремится иметь знакомый синтаксис для программистов C/C++, ключевое слово static здесь уместно.
class C {
int foo = 1;
static int bar = 2;
:
}
Наконец, мы подошли к методам.
class C {
int foo() { ... }
static int bar() { ... }
:
}
С концептуальной точки зрения существует экземпляр foo() для каждого экземпляра класса C. Существует только один экземпляр bar() для всего класса C. Это аналогично случаю, который мы обсуждали для данных, и, следовательно, с использованием 'static'снова является разумным выбором, особенно если вы не хотите добавлять на свой язык больше зарезервированных ключевых слов.
Статические переменные могут быть доступны только в статических методах, поэтому, когда мы объявляем статические переменные, методы getter и setter будут статическими методами.
статические методы - это уровень класса, к которому мы можем получить доступ, используя имя класса
Ниже приведен пример для статических переменных Getter и Setters:
public class Static
{
private static String owner;
private static int rent;
private String car;
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public static int getRent() {
return rent;
}
public static void setRent(int rent) {
Static.rent = rent;
}
public static String getOwner() {
return owner;
}
public static void setOwner(String owner) {
Static.owner = owner;
}
}
При запуске какого-то проекта сначала загружаются статические вещи (переменные, методы, блоки..).
При запуске этого проекта основной метод загружается первым. Потому что это static method
, Тогда смотри объект "a" object
.Но объект еще не определен. Потому что это не статично. Тогда приходите, как эта ошибка.
Член в программе Java может быть объявлен как статический, используя ключевое слово «static» перед его объявлением / определением. Когда член объявлен статическим, это, по сути, означает, что член используется всеми экземплярами класса без создания копий для каждого экземпляра.
Таким образом, static является неклассовым модификатором, используемым в Java, и может применяться к следующим членам:
- Переменные
- Методы
- Блоки
- Классы (точнее, вложенные классы)
Когда член объявлен статическим, к нему можно получить доступ без использования объекта. Это означает, что до создания экземпляра класса статический член активен и доступен. В отличие от других нестатических членов класса, которые перестают существовать, когда объект класса выходит за пределы области видимости, статический член по-прежнему явно активен.
Статическая переменная в Java
Переменная-член класса, объявленного как статический, называется статической переменной. Ее также называют «переменной класса». После того, как переменная объявлена как статическая, память выделяется только один раз, а не каждый раз при создании экземпляра класса. Следовательно, вы можете получить доступ к статической переменной без ссылки на объект.
Следующая программа на Java описывает использование статических переменных:
class Main
{
// static variables a and b
static int a = 10;
static int b;
static void printStatic()
{
a = a /2;
b = a;
System.out.println("printStatic::Value of a : "+a + " Value of b :
"+b);
}
public static void main(String[] args)
{
printStatic();
b = a*5;
a++;
System.out.println("main::Value of a : "+a + " Value of b : "+b);
}
}
выход::
printStatic::Value of a : Value of b : 5
main::Value of a : 6 Value of b : 25
В приведенной выше программе у нас есть две статические переменные, то есть a и b. Мы изменяем эти переменные как в функции printStatic, так и в функции main. Обратите внимание, что значения этих статических переменных сохраняются во всех функциях, даже когда область действия функции заканчивается. Выходные данные показывают значения переменных в двух функциях.
Статический метод
Метод в Java является статическим, если ему предшествует ключевое слово static.
Некоторые моменты, которые вам нужно помнить о статическом методе, включают:
- Статический метод принадлежит классу в отличие от других нестатических методов, которые вызываются с использованием экземпляра класса.
- Чтобы вызвать статический метод, вам не нужен объект класса.
- Статические члены данных класса доступны статическому методу. Статический метод может даже изменять значения статического элемента данных.
- Статический метод не может иметь ссылки на члены this или super. Даже если статический метод попытается ссылаться на них, это будет ошибкой компилятора.
- Как и статические данные, статический метод также может вызывать другие статические методы. Статический метод не может ссылаться на нестатические элементы данных или переменные, а также не может вызывать нестатические методы.
Следующая программа показывает реализацию статического метода на Java:
class Main
{
// static method
static void static_method()
{
System.out.println("Static method in Java...called without any
object");
}
public static void main(String[] args)
{
static_method();
}
}
выход:
Static method in Java...called without any object
Статический блок в Java
Так же, как у вас есть функциональные блоки в языках программирования, таких как C ++, C # и т. Д., В Java также есть специальный блок, называемый «статическим» блоком, который обычно включает блок кода, связанный со статическими данными.
Этот статический блок выполняется в момент создания первого объекта класса (именно во время загрузки класса) или когда используется статический член внутри блока.
Следующая программа показывает использование статического блока.
class Main
{
static int sum = 0;
static int val1 = 5;
static int val2;
// static block
static {
sum = val1 + val2;
System.out.println("In static block, val1: " + val1 + " val2: "+
val2 + " sum:" + sum);
val2 = val1 * 3;
sum = val1 + val2;
}
public static void main(String[] args)
{
System.out.println("In main function, val1: " + val1 + " val2: "+ val2 + " sum:" + sum);
}
}
выход:
In static block, val1: 5 val2: 0 sum:5
In main function, val1: val2: 15 sum:20
Статический класс
В Java у вас есть статические блоки, статические методы и даже статические переменные. Следовательно, очевидно, что у вас также могут быть статические классы. В Java можно иметь класс внутри другого класса, и это называется вложенным классом. Класс, который включает вложенный класс, называется внешним классом.
В Java, хотя вы можете объявить вложенный класс как статический, невозможно сделать внешний класс статическим.
Давайте теперь исследуем статические вложенные классы в Java.
Статический вложенный класс
Как уже упоминалось, у вас может быть вложенный класс в Java, объявленный как статический. Статический вложенный класс отличается от нестатического вложенного класса (внутреннего класса) в некоторых аспектах, перечисленных ниже.
В отличие от нестатического вложенного класса, вложенный статический класс не требует ссылки на внешний класс.
Статический вложенный класс может обращаться только к статическим членам внешнего класса, в отличие от нестатических классов, которые могут обращаться как к статическим, так и к нестатическим членам внешнего класса.
Пример статического вложенного класса приведен ниже.
class Main{
private static String str = "SoftwareTestingHelp";
//Static nested class
static class NestedClass{
//non-static method
public void display() {
System.out.println("Static string in OuterClass: " + str);
}
}
public static void main(String args[])
{
Main.NestedClassobj = new Main.NestedClass();
obj.display();
}
}
выход
Static string in OuterClass: SoftwareTestingHelp
Я думаю, что именно так работает ключевое слово static в java.