private final static -> создать эту переменную только один раз. private final -> создать эту переменную для каждого объекта. Сначала человек сохраняет память, дерзай.
user1923551
4
final staticозначает, что эта переменная является константой и ассоциируется только с самим классом, то есть «одна постоянная переменная на класс», тогда как finalозначает «одна постоянная переменная на экземпляр». В результате вы не можете поместить final staticпеременную в конструктор класса, так как конструктор включает новый экземпляр . (Вы можете попробовать это сами и получите ошибку)
LittleLittleQ
1
Под «не могу поместить окончательную статическую переменную в конструктор класса» я имею в виду, что нельзя инициализировать final staticпеременную в конструкторе, единственный способ - использовать статический инициализатор :)
LittleLittleQ
2
@ user1923551 Эффект инвертируется для вещей, которые нужны только в течение ограниченного периода времени в больших приложениях, в приложениях с дефицитом памяти или при использовании одиночного файла. Наличие статических вещей в каждом классе зарезервирует (огромный) кусок памяти для ненужных вещей. Это также может быть утечка памяти для объявления статических конечных объектов или коллекций.
Надеюсь, что
Ответы:
309
В общем, staticозначает «связанный с самим типом , а не с экземпляром типа».
Это означает, что вы можете ссылаться на статическую переменную, даже не создавая экземпляры типа, и любой код, ссылающийся на переменную, ссылается на те же самые данные. Сравните это с переменной экземпляра: в этом случае для каждого экземпляра класса существует одна независимая версия переменной. Так, например:
Test x =newTest();Test y =newTest();
x.instanceVariable =10;
y.instanceVariable =20;System.out.println(x.instanceVariable);
выводит 10: y.instanceVariableи x.instanceVariableявляются отдельными, потому что xи yотносятся к разным объектам.
Вы можете ссылаться на статические члены через ссылки, хотя это плохая идея. Если бы мы сделали:
Test x =newTest();Test y =newTest();
x.staticVariable =10;
y.staticVariable =20;System.out.println(x.staticVariable);
тогда это напечатало бы 20 - есть только одна переменная, не одна на экземпляр. Было бы яснее написать это так:
Test x =newTest();Test y =newTest();Test.staticVariable =10;Test.staticVariable =20;System.out.println(Test.staticVariable);
Это делает поведение намного более очевидным. Современные IDE обычно предлагают изменить второй листинг на третий.
Нет причин иметь встроенное объявление, инициализирующее значение, подобное следующему, поскольку каждый экземпляр будет иметь свое собственное значение, NUMBERно всегда с одним и тем же значением (является неизменным и инициализируется литералом). Это то же самое, что иметь только одну final staticпеременную для всех экземпляров.
privatefinalint NUMBER =10;
Поэтому, если он не может измениться, нет смысла иметь одну копию на экземпляр.
Но это имеет смысл, если инициализируется в конструкторе следующим образом:
// No initialization when is declaredprivatefinalint number;publicMyClass(int n){// The variable can be assigned in the constructor, but then// not modified later.
number = n;}
Теперь для каждого экземпляра у MyClassнас может быть другое, но неизменное значение number.
Пока перечисления не были доступны в Java 5, статический финал был обычным способом объявления констант.
Винит Рейнольдс
22
@Vineet: статические финалы по-прежнему являются способом объявления примитивных констант, если только у вас нет перечисленных их значений =)
Chii
@ Матфея: потенциально. Не для константы, а для некоторого логически связанного с экземпляром значения. Не то чтобы мне все равно нравились одиночные игры.
Джон Скит
1
Радикальный вопрос. Стоит ли использовать private finalболееprivate static final чтобы выжать / вернуть ту небольшую память из класса? Скажем, для calculatorустройства с ограниченной оперативной памятью, но большим количеством ресурсов процессора.
Выиграй Myo Htet
1
@WinMyoHtet: если вы используете статическое поле, всего одно . Если вы используете поле экземпляра, есть одно на экземпляр. Использование статического поля будет лучше, если у вас нет экземпляров, и в любом случае это бесполезно.
Джон Скит
38
Для финала , ему могут быть присвоены разные значения во время выполнения при инициализации. Например
Таким образом, каждый экземпляр имеет различное значение поля a .
Для статического final все экземпляры имеют одинаковое значение и не могут быть изменены после первой инициализации.
ClassTestStatic{publicstaticfinalint a;}TestStatic t1 =newTestStatic();
t1.a =10;TestStatic t2 =newTestStatic();
t1.a =20;// ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.
Это не скомпилируется! Конечная переменная должна либо иметь значение, либо иметь значение, назначенное в ее конструкторах. Этот ответ был бы правильным, если бы были заданы 2 конструктора, каждый из которых присваивал «a» разное значение.
MattC
14
Подтверждение, это не будет компилироваться. Как выражено выше, конечные переменные экземпляра должны быть созданы до завершения конструктора, а конечные переменные класса должны быть созданы до того, как класс был создан (вы можете использовать статический блок). Почему так много голосов?
Руди Кершоу
как указал MattC, вы не можете назначить конечную переменную после создания этого объекта - на самом деле, вы даже не можете создать объект, не задав значения для его конечных переменных ...
jamesdeath123
На всякий случай, если кто-нибудь наткнется на это, пожалуйста, следуйте ответу MattC.
Фаз
Это то, о чем, по-моему, спрашивал ОП, я забыл, что финалам можно присвоить значение при создании экземпляра, если оно не было указано при объявлении.
Salsero69
34
А staticпеременная остается в памяти на всю жизнь приложения, и инициализируется во время загрузки класса. Не staticпеременная инициализируется каждый раз, когда вы создаете newобъект. Как правило, лучше использовать:
privatestaticfinalint NUMBER =10;
Зачем? Это уменьшает объем памяти на экземпляр. Возможно, это также благоприятно для попаданий в кэш. И это просто имеет смысл: staticдолжно использоваться для вещей, которые являются общими для всех экземпляров (или объектов) определенного типа (также известных class).
статическая переменная также создается во время выполнения. Поэтому вы можете использовать указанную переменную или метод до создания объекта.
Бобби
13
Согласно соглашению о кодировании Java, имя статической конечной переменной должно быть в верхнем регистре.
звездный синий
@Martijn Courteaux, как насчет ситуации, когда класс будет использоваться один раз за время существования приложения! private final intбудет удален из памяти, когда экземпляр будет собран GC, тогда как private static final intон останется в памяти на протяжении всей жизни этого приложения. Что вы предлагаете в приведенном выше сценарии?
MANN
@MANN: это очень теоретически. Буквально нет полезного сценария использования для этого. Это может быть полезно, если у вас около 50000 int vars в классе. Даже в этом случае это сэкономит 200 КБ памяти. Поскольку мы говорим на Java, это кажется совершенно неактуальным. В случае устройств, критичных к памяти, приличный компилятор C или C ++ всегда вставляет эти целочисленные значения, устраняя необходимость полного освобождения памяти.
Мартин Курто
17
статический означает «связанный с классом»; без него переменная связана с каждым экземпляром класса. Если он статический, это означает, что у вас будет только один в памяти; если нет, у вас будет один для каждого создаваемого вами экземпляра. static означает, что переменная будет оставаться в памяти до тех пор, пока класс загружен; без него переменная может быть gc'd, когда ее экземпляр.
Переменные экземпляра получают gc'd всякий раз, когда все ссылки / объекты на него умирают, верно?
Ручир Барония
Экземпляры gc'd, но статика связана с классами, а не с экземплярами. Пока класс остается в памяти, вы сможете ссылаться на его открытые статические экземпляры и методы. Они входят в perm gen (или каков его эквивалент JDK 8) и не являются gc'd.
duffymo
Неправильно. Если у вас есть ссылка на экземпляр в памяти, вы можете получить доступ к его доступным методам и экземплярам. Остальное не так. Вы не понимаете разницу между классом и его экземплярами.
duffymo
13
Читая ответы, я не нашел ни одного реального теста, подходящего к сути. Вот мои 2 цента:
Как я и думал, Java делает разницу между примитивными и другими типами. Примитивные типы в Java всегда «кэшируются», то же самое для строковых литералов (не новых объектов String), поэтому нет разницы между статическими и нестатическими членами.
Однако существует дублирование памяти для нестатических элементов, если они не являются экземплярами примитивного типа.
Изменение значения valueStatic на 10 пойдет даже дальше, поскольку Java будет давать одинаковые адреса двум переменным int.
Автобокс 'int' -> Integer вызывает здесь путаницу. Вы видите, что автобокс некоторых (маленьких) значений int приводит к одному и тому же объекту Integer.
dkneller
@StackHola @dkneller Действительно, автобокс - очень важная деталь, которая происходит здесь. Подпись есть ObjectUtils.identityToString(Object). (Кроме того, Java в любом случае не передает ссылки). Реальным полезным тестом было бы выделить два объекта и public final int FOO = 10принудительно изменить значение переменной, используя отражения Java. Затем проверьте, не изменился ли другой объект.
Мартин Курто
11
В то время как другие ответы, по-видимому, ясно показывают, что, как правило, нет причин использовать нестатические константы, я не смог найти никого, кто бы указывал на то, что можно иметь различные экземпляры с разными значениями для их постоянных переменных.
Рассмотрим следующий пример:
publicclassTestClass{privatefinalstaticdouble NUMBER =Math.random();publicTestClass(){System.out.println(NUMBER);}}
Создание трех экземпляров TestClass напечатало бы одно и то же случайное значение три раза, поскольку генерируется только одно значение и сохраняется в статической константе.
Однако при попытке использовать следующий пример:
publicclassTestClass{privatefinaldouble NUMBER =Math.random();publicTestClass(){System.out.println(NUMBER);}}
Создание трех экземпляров TestClass теперь выводит три разных случайных значения, потому что каждый экземпляр имеет свое собственное случайно сгенерированное постоянное значение.
Я не могу вспомнить ни одной ситуации, когда было бы действительно полезно иметь разные постоянные значения в разных случаях, но я надеюсь, что это помогает подчеркнуть, что между статическими и нестатическими финалами есть четкое различие.
publicclassStaticVariable{staticint noOfInstances;StaticVariable(){
noOfInstances++;}publicstaticvoid main(String[] args){StaticVariable sv1 =newStaticVariable();System.out.println("No. of instances for sv1 : "+ sv1.noOfInstances);StaticVariable sv2 =newStaticVariable();System.out.println("No. of instances for sv1 : "+ sv1.noOfInstances);System.out.println("No. of instances for st2 : "+ sv2.noOfInstances);StaticVariable sv3 =newStaticVariable();System.out.println("No. of instances for sv1 : "+ sv1.noOfInstances);System.out.println("No. of instances for sv2 : "+ sv2.noOfInstances);System.out.println("No. of instances for sv3 : "+ sv3.noOfInstances);}}
Вывод программы приведен ниже:
Как мы видим в этом примере, каждый объект имеет свою собственную копию переменной класса.
C:\java>java StaticVariableNo. of instances for sv1 :1No. of instances for sv1 :2No. of instances for st2 :2No. of instances for sv1 :3No. of instances for sv2 :3No. of instances for sv3 :3
Из тестов, которые я сделал, статические конечные переменные не совпадают с конечными (нестатическими) переменными! Конечные (нестатические) переменные могут отличаться от объекта к объекту !!! Но это только в том случае, если инициализация выполняется внутри конструктора! (Если он не инициализирован из конструктора, то это только пустая трата памяти, поскольку он создает окончательные переменные для каждого создаваемого объекта, которые нельзя изменить.)
Например:
class A
{finalint f;staticfinalint sf =5;
A(int num){this.f = num;}void show(){System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n",this.toString(),this.f, sf);}publicstaticvoid main(String[] args){
A ob1 =new A(14);
ob1.show();
A ob2 =new A(21);
ob2.show();}}
На экране появляется следующее:
Об объекте: A @ addbf1 Финал: 14 Статический Финал: 5
Об объекте: A @ 530daa Финал: 21 Статический финал: 5
Кроме того, к ответу Джона, если вы используете static final, он будет вести себя как своего рода «определение». Как только вы скомпилируете класс, который его использует, он будет сожжен в скомпилированном файле .class. Проверьте мою ветку об этом здесь .
Для вашей главной цели: если вы не используете NUMBER по-разному в разных экземплярах класса, я бы посоветовал использовать final и static.
(Вы просто должны помнить, чтобы не копировать скомпилированные файлы классов без учета возможных проблем, подобных описанным в моем примере. В большинстве случаев этого не происходит, не волнуйтесь :))
Чтобы показать, как использовать разные значения в экземплярах, проверьте этот код:
package test;publicclassTest{finallong OBJECT_ID =newRandom().nextLong();finalstaticlong CLASSS_ID =newRandom().nextLong();publicstaticvoid main(String[] args){Test[] test =newTest[5];for(int i =0; i < test.length; i++){
test[i]=newTest();System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same valueSystem.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different}}}
Ключевым моментом является то, что переменные и функции могут возвращать разные значения. Поэтому конечные переменные могут быть назначены с разными значениями.
Еще один простой пример, чтобы понять использование статических, статических финальных, конечных переменных. Комментарии к коду имеют правильное объяснение.
publicclassCity{// base price that is always same for all objects[For all cities].privatestaticdouble iphone_base_price =10000;// this is total price = iphone_base_price+iphone_diff;privatedouble iphone_citi_price;// extra price added to iphone_base_price. It is constant per city. Every// city has its own difference defined,privatefinaldouble iphone_diff;privateString cityName ="";// static final will be accessible everywhere within the class but cant be// changed once initialized.privatestaticfinalString countryName ="India";publicCity(String cityName,double iphone_diff){super();this.iphone_diff = iphone_diff;
iphone_citi_price = iphone_base_price + iphone_diff;this.cityName = cityName;}/**
* get phone price
*
* @return
*/privatedouble getPrice(){return iphone_citi_price;}/**
* Get city name
*
* @return
*/privateString getCityName(){return cityName;}publicstaticvoid main(String[] args){// 300 is theCity newyork =newCity("Newyork",300);System.out.println(newyork.getPrice()+" "+ newyork.getCityName());City california =newCity("California",800);System.out.println(california.getPrice()+" "+ california.getCityName());// We cant write below statement as a final variable can not be// reassigned// california.iphone_diff=1000; //************************// base price is defined for a class and not per instances.// For any number of object creation, static variable's value would be the same// for all instances until and unless changed.// Also it is accessible anywhere inside a class.
iphone_base_price =9000;City delhi =newCity("delhi",400);System.out.println(delhi.getPrice()+" "+ delhi.getCityName());City moscow =newCity("delhi",500);System.out.println(moscow.getPrice()+" "+ moscow.getCityName());// Here countryName is accessible as it is static but we can not change it as it is final as well. //Something are meant to be accessible with no permission to modify it. //Try un-commenting below statementsSystem.out.println(countryName);// countryName="INDIA";// System.out.println(countryName);}}
Разницы не так много, поскольку они оба постоянные. Для большинства объектов данных класса static будет означать что-то, связанное с самим классом, поскольку существует только одна копия, независимо от того, сколько объектов было создано с новым.
Поскольку он является константой, он может не храниться ни в классе, ни в экземпляре, но компилятор по-прежнему не позволит вам получить доступ к объектам экземпляра из статического метода, даже если он знает, какими они будут. Существование API отражения также может потребовать некоторой бессмысленной работы, если вы не сделаете его статичным.
Поскольку переменная в классе объявляется как final и инициализируется в той же команде, нет абсолютно никаких причин не объявлять ее как статическую, поскольку она будет иметь одно и то же значение независимо от экземпляра. Таким образом, все экземпляры могут совместно использовать один и тот же адрес памяти для значения, тем самым экономя время обработки, устраняя необходимость создавать новую переменную для каждого экземпляра и экономя память путем совместного использования 1 общего адреса.
Закрытый статический финал будет считаться константой, а константа может быть доступна только внутри этого класса. Поскольку ключевое слово static включено, значение будет постоянным для всех объектов класса.
Закрытое окончательное значение переменной будет как константа для объекта.
Вы можете сослаться на java.lang.String или посмотреть пример ниже.
Статический элемент является одним и тем же членом во всех экземплярах класса и самого класса.
Нестатический - один для каждого экземпляра (объекта), так что в вашем конкретном случае это пустая трата памяти, если вы не установите static.
Если вы пометите эту переменную как статическую, то, как вы знаете, вам потребуется статические методы для повторного доступа к этим значениям, это будет полезно, если вы уже думаете об использовании этих переменных только в статических методах. Если это так, то это будет лучшим.
Однако теперь вы можете сделать переменную общедоступной, поскольку никто не может изменить ее так же, как «System.out», она снова зависит от ваших намерений и того, чего вы хотите достичь.
Статические методы не потребуются для доступа к статическим переменным - я думаю, что вы думаете о «доступе к переменным экземпляра из статических методов» (недопустимо).
Ataulm
0
Скажем, если у класса не будет больше одного экземпляра, какой из них занимает больше памяти:
приватная статическая конечная int ID = 250; или приватный конечный int ID = 250;
Я понял, что static будет ссылаться на тип класса только с одной копией в памяти, а non static будет в новом месте памяти для каждой переменной экземпляра. Однако внутренне, если мы просто сравним 1 экземпляр одного и того же класса когда-либо (то есть более 1 экземпляр не будет создан), то есть ли какие-либо издержки с точки зрения пространства, используемого 1 статической конечной переменной?
Пожалуйста, не просто повторяйте, что другие ответы уже охватили.
пользователь неизвестен
0
Статическая переменная принадлежит классу (что означает, что все объекты имеют эту переменную). Нестатическая переменная принадлежит каждому объекту.
publicclassExperimentFinal{privatefinalint a;privatestaticfinalint b =999;publicExperimentFinal(int a){super();this.a = a;}publicint getA(){return a;}publicint getB(){return b;}publicvoid print(int a,int b){System.out.println("final int: "+ a +" \nstatic final int: "+ b);}publicstaticvoid main(String[] args){ExperimentFinal test =newExperimentFinal(9);
test.print(test.getA(), test.getB());}}
Как видно из приведенного выше примера, для «final int» мы можем назначить нашу переменную для каждого экземпляра (объекта) класса, однако для «static final int» мы должны назначить переменную в классе (статическая переменная принадлежит классу ).
Конечная: после назначения конечной переменной она всегда содержит одно и то же значение. где переменная является статической или не статической: это будет только одна переменная для всех экземпляров, инициализированных один раз в памяти
publicclassLengthDemo{publicstaticvoid main(String[] args){Rectangle box =newRectangle();System.out.println("Sending the value 10.0 "+"to the setLength method.");
box.setLength(10.0);System.out.println("Done.");}}
Ключевое слово «Static» создает свойство переменной класса, а не отдельные экземпляры класса. Будет одна копия этой переменной, которая является общей для всех экземпляров этого класса. Любое изменение состояния статической переменной будет отражено во всех экземплярах. Добавьте final к static, и мы получим переменную, которая была инициализирована раз и навсегда во время загрузки класса и не может быть изменена позже ни одним экземпляром класса. Статические конечные переменные должны быть инициализированы во время объявления, иначе у нас будет ошибка времени компиляции. Что касается частного поля экземпляра, оно относится к свойству / состоянию объекта / экземпляра класса. Каждый экземпляр / объект класса будет иметь свою собственную копию переменной экземпляра. Когда переменная экземпляра объявлена финальной, это означает, что мы не можем изменить его значение для этого экземпляра. Для этого нам нужно инициализировать конечную переменную либо в объявлении, либо в конструкторе. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Для этого нам нужно инициализировать конечную переменную либо в объявлении, либо в конструкторе. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Для этого нам нужно инициализировать конечную переменную либо в объявлении, либо в конструкторе. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта.
final static
означает, что эта переменная является константой и ассоциируется только с самим классом, то есть «одна постоянная переменная на класс», тогда какfinal
означает «одна постоянная переменная на экземпляр». В результате вы не можете поместитьfinal static
переменную в конструктор класса, так как конструктор включает новый экземпляр . (Вы можете попробовать это сами и получите ошибку)final static
переменную в конструкторе, единственный способ - использовать статический инициализатор :)Ответы:
В общем,
static
означает «связанный с самим типом , а не с экземпляром типа».Это означает, что вы можете ссылаться на статическую переменную, даже не создавая экземпляры типа, и любой код, ссылающийся на переменную, ссылается на те же самые данные. Сравните это с переменной экземпляра: в этом случае для каждого экземпляра класса существует одна независимая версия переменной. Так, например:
выводит 10:
y.instanceVariable
иx.instanceVariable
являются отдельными, потому чтоx
иy
относятся к разным объектам.Вы можете ссылаться на статические члены через ссылки, хотя это плохая идея. Если бы мы сделали:
тогда это напечатало бы 20 - есть только одна переменная, не одна на экземпляр. Было бы яснее написать это так:
Это делает поведение намного более очевидным. Современные IDE обычно предлагают изменить второй листинг на третий.
Нет причин иметь встроенное объявление, инициализирующее значение, подобное следующему, поскольку каждый экземпляр будет иметь свое собственное значение,
NUMBER
но всегда с одним и тем же значением (является неизменным и инициализируется литералом). Это то же самое, что иметь только однуfinal static
переменную для всех экземпляров.Поэтому, если он не может измениться, нет смысла иметь одну копию на экземпляр.
Но это имеет смысл, если инициализируется в конструкторе следующим образом:
Теперь для каждого экземпляра у
MyClass
нас может быть другое, но неизменное значениеnumber
.источник
private final
болееprivate static final
чтобы выжать / вернуть ту небольшую память из класса? Скажем, дляcalculator
устройства с ограниченной оперативной памятью, но большим количеством ресурсов процессора.Для финала , ему могут быть присвоены разные значения во время выполнения при инициализации. Например
Таким образом, каждый экземпляр имеет различное значение поля a .
Для статического final все экземпляры имеют одинаковое значение и не могут быть изменены после первой инициализации.
источник
А
static
переменная остается в памяти на всю жизнь приложения, и инициализируется во время загрузки класса. Неstatic
переменная инициализируется каждый раз, когда вы создаетеnew
объект. Как правило, лучше использовать:Зачем? Это уменьшает объем памяти на экземпляр. Возможно, это также благоприятно для попаданий в кэш. И это просто имеет смысл:
static
должно использоваться для вещей, которые являются общими для всех экземпляров (или объектов) определенного типа (также известныхclass
).источник
private final int
будет удален из памяти, когда экземпляр будет собран GC, тогда какprivate static final int
он останется в памяти на протяжении всей жизни этого приложения. Что вы предлагаете в приведенном выше сценарии?статический означает «связанный с классом»; без него переменная связана с каждым экземпляром класса. Если он статический, это означает, что у вас будет только один в памяти; если нет, у вас будет один для каждого создаваемого вами экземпляра. static означает, что переменная будет оставаться в памяти до тех пор, пока класс загружен; без него переменная может быть gc'd, когда ее экземпляр.
источник
Читая ответы, я не нашел ни одного реального теста, подходящего к сути. Вот мои 2 цента:
Результаты для первого объекта:
Результаты для 2-го объекта:
Вывод :
Как я и думал, Java делает разницу между примитивными и другими типами. Примитивные типы в Java всегда «кэшируются», то же самое для строковых литералов (не новых объектов String), поэтому нет разницы между статическими и нестатическими членами.
Однако существует дублирование памяти для нестатических элементов, если они не являются экземплярами примитивного типа.
Изменение значения valueStatic на 10 пойдет даже дальше, поскольку Java будет давать одинаковые адреса двум переменным int.
источник
ObjectUtils.identityToString(Object)
. (Кроме того, Java в любом случае не передает ссылки). Реальным полезным тестом было бы выделить два объекта иpublic final int FOO = 10
принудительно изменить значение переменной, используя отражения Java. Затем проверьте, не изменился ли другой объект.В то время как другие ответы, по-видимому, ясно показывают, что, как правило, нет причин использовать нестатические константы, я не смог найти никого, кто бы указывал на то, что можно иметь различные экземпляры с разными значениями для их постоянных переменных.
Рассмотрим следующий пример:
Создание трех экземпляров TestClass напечатало бы одно и то же случайное значение три раза, поскольку генерируется только одно значение и сохраняется в статической константе.
Однако при попытке использовать следующий пример:
Создание трех экземпляров TestClass теперь выводит три разных случайных значения, потому что каждый экземпляр имеет свое собственное случайно сгенерированное постоянное значение.
Я не могу вспомнить ни одной ситуации, когда было бы действительно полезно иметь разные постоянные значения в разных случаях, но я надеюсь, что это помогает подчеркнуть, что между статическими и нестатическими финалами есть четкое различие.
источник
Как уже сказал Джон, статическая переменная, также называемая переменной класса, является переменной, которая существует во всех экземплярах класса.
Я нашел пример этого здесь :
Вывод программы приведен ниже:
Как мы видим в этом примере, каждый объект имеет свою собственную копию переменной класса.
источник
Из тестов, которые я сделал, статические конечные переменные не совпадают с конечными (нестатическими) переменными! Конечные (нестатические) переменные могут отличаться от объекта к объекту !!! Но это только в том случае, если инициализация выполняется внутри конструктора! (Если он не инициализирован из конструктора, то это только пустая трата памяти, поскольку он создает окончательные переменные для каждого создаваемого объекта, которые нельзя изменить.)
Например:
На экране появляется следующее:
Об объекте: A @ addbf1 Финал: 14 Статический Финал: 5
Об объекте: A @ 530daa Финал: 21 Статический финал: 5
Анонимный студент 1 курса IT, Греция
источник
Кроме того, к ответу Джона, если вы используете static final, он будет вести себя как своего рода «определение». Как только вы скомпилируете класс, который его использует, он будет сожжен в скомпилированном файле .class. Проверьте мою ветку об этом здесь .
Для вашей главной цели: если вы не используете NUMBER по-разному в разных экземплярах класса, я бы посоветовал использовать final и static. (Вы просто должны помнить, чтобы не копировать скомпилированные файлы классов без учета возможных проблем, подобных описанным в моем примере. В большинстве случаев этого не происходит, не волнуйтесь :))
Чтобы показать, как использовать разные значения в экземплярах, проверьте этот код:
источник
Вот мои два цента:
Пример:
Ключевым моментом является то, что переменные и функции могут возвращать разные значения. Поэтому конечные переменные могут быть назначены с разными значениями.
источник
Еще один простой пример, чтобы понять использование статических, статических финальных, конечных переменных. Комментарии к коду имеют правильное объяснение.
источник
очень мало и статично
Разницы не так много, поскольку они оба постоянные. Для большинства объектов данных класса static будет означать что-то, связанное с самим классом, поскольку существует только одна копия, независимо от того, сколько объектов было создано с новым.
Поскольку он является константой, он может не храниться ни в классе, ни в экземпляре, но компилятор по-прежнему не позволит вам получить доступ к объектам экземпляра из статического метода, даже если он знает, какими они будут. Существование API отражения также может потребовать некоторой бессмысленной работы, если вы не сделаете его статичным.
источник
Поскольку переменная в классе объявляется как final и инициализируется в той же команде, нет абсолютно никаких причин не объявлять ее как статическую, поскольку она будет иметь одно и то же значение независимо от экземпляра. Таким образом, все экземпляры могут совместно использовать один и тот же адрес памяти для значения, тем самым экономя время обработки, устраняя необходимость создавать новую переменную для каждого экземпляра и экономя память путем совместного использования 1 общего адреса.
источник
Закрытый статический финал будет считаться константой, а константа может быть доступна только внутри этого класса. Поскольку ключевое слово static включено, значение будет постоянным для всех объектов класса.
Закрытое окончательное значение переменной будет как константа для объекта.
Вы можете сослаться на java.lang.String или посмотреть пример ниже.
//Вывод:
источник
Статический элемент является одним и тем же членом во всех экземплярах класса и самого класса.
Нестатический - один для каждого экземпляра (объекта), так что в вашем конкретном случае это пустая трата памяти, если вы не установите static.
источник
Если вы пометите эту переменную как статическую, то, как вы знаете, вам потребуется статические методы для повторного доступа к этим значениям, это будет полезно, если вы уже думаете об использовании этих переменных только в статических методах. Если это так, то это будет лучшим.
Однако теперь вы можете сделать переменную общедоступной, поскольку никто не может изменить ее так же, как «System.out», она снова зависит от ваших намерений и того, чего вы хотите достичь.
источник
Скажем, если у класса не будет больше одного экземпляра, какой из них занимает больше памяти:
приватная статическая конечная int ID = 250; или приватный конечный int ID = 250;
Я понял, что static будет ссылаться на тип класса только с одной копией в памяти, а non static будет в новом месте памяти для каждой переменной экземпляра. Однако внутренне, если мы просто сравним 1 экземпляр одного и того же класса когда-либо (то есть более 1 экземпляр не будет создан), то есть ли какие-либо издержки с точки зрения пространства, используемого 1 статической конечной переменной?
источник
Статическая переменная принадлежит классу (что означает, что все объекты имеют эту переменную). Нестатическая переменная принадлежит каждому объекту.
Как видно из приведенного выше примера, для «final int» мы можем назначить нашу переменную для каждого экземпляра (объекта) класса, однако для «static final int» мы должны назначить переменную в классе (статическая переменная принадлежит классу ).
источник
Если вы используете static, значение переменной будет одинаковым во всех ваших экземплярах, при изменении в одном экземпляре другие тоже изменятся.
источник
Конечная: после назначения конечной переменной она всегда содержит одно и то же значение. где переменная является статической или не статической: это будет только одна переменная для всех экземпляров, инициализированных один раз в памяти
источник
Это может помочь
источник
Ключевое слово «Static» создает свойство переменной класса, а не отдельные экземпляры класса. Будет одна копия этой переменной, которая является общей для всех экземпляров этого класса. Любое изменение состояния статической переменной будет отражено во всех экземплярах. Добавьте final к static, и мы получим переменную, которая была инициализирована раз и навсегда во время загрузки класса и не может быть изменена позже ни одним экземпляром класса. Статические конечные переменные должны быть инициализированы во время объявления, иначе у нас будет ошибка времени компиляции. Что касается частного поля экземпляра, оно относится к свойству / состоянию объекта / экземпляра класса. Каждый экземпляр / объект класса будет иметь свою собственную копию переменной экземпляра. Когда переменная экземпляра объявлена финальной, это означает, что мы не можем изменить его значение для этого экземпляра. Для этого нам нужно инициализировать конечную переменную либо в объявлении, либо в конструкторе. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Для этого нам нужно инициализировать конечную переменную либо в объявлении, либо в конструкторе. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Для этого нам нужно инициализировать конечную переменную либо в объявлении, либо в конструкторе. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Если это не сделано ни в одном из них, появится ошибка времени компиляции. После инициализации, если вы попытаетесь переназначить значение, вы получите ошибку времени компиляции. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Используйте статические конечные переменные, где данные будут совместно использоваться во всех экземплярах класса, и вы хотите, чтобы данные были доступны только для чтения. Используйте конечную переменную экземпляра, если вы хотите представить некоторые данные, которые принадлежат каждому отдельному экземпляру класса, но один раз сохраненный не может быть изменен. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта. Использование статического и ключевого слова экземпляра зависит от ваших требований к дизайну и того, что эти данные представляют в домене. Если данные используются в экземплярах класса, то нет необходимости в отдельных копиях / ссылках на память для каждого объекта.
источник