Могут ли существовать две копии переменной класса?

У меня есть класс Car, который имеет стоимость переменной области класса, я понимаю, что это плохая идея на практике, просто пытаюсь понять влияние переменных класса общедоступной области.

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

public class Car{
  public static int cost;

  public Car(int cost){
     cost = cost;
  }
}

public static void main(String args[]){
  Car car = new Car(2);      
}

person Oh Chin Boon    schedule 19.10.2011    source источник
comment
Это может представлять интерес: stackoverflow.com/questions/5950025 /   -  person NPE    schedule 19.10.2011
comment
возможный дубликат возможно ли иметь несколько экземпляров статических переменные   -  person NPE    schedule 19.10.2011


Ответы (5)


Указав поле cost как static, вы говорите, что всегда будет только один общий экземпляр этой переменной, независимо от того, сколько классов Car создано (в процессе). И да, любой из этих экземпляров сможет изменять это единственное общее поле, и поскольку вы сделали его общедоступным, то же самое сделает любой другой клиентский код, имеющий доступ к классу Car. (Другие процессы, которые могут использовать те же классы, будут иметь свои собственные копии членов статического класса и не смогут «видеть» границы процесса.)

С точки зрения семантики, и если я правильно вывожу значение для автомобиля и стоимости, вы не хотите использовать статическое значение, ЕСЛИ вы не хотите, чтобы ВСЕ ваши автомобили стоили одинаково. В реальном мире стоимость автомобиля является сильно различающимся атрибутом даже между одной и той же моделью автомобиля одной и той же марки из-за отделки салона, опций и т. д.

person Paul Sasik    schedule 19.10.2011

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

Как побочное примечание, это не будет делать то, что вы думаете:

public Car(int cost)
{
  cost = cost;
}

Здесь вы назначаете параметр самому себе (если вы сделаете его окончательным, вы должны получить ошибку компилятора), а не параметр статической переменной. Это также называется слежкой и плохой практикой.

person Thomas    schedule 19.10.2011

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

public Car(int cost)
{
  Car.cost = cost;
}

Не обращайтесь к переменной области класса (статической стоимости) с помощью this.cost. Вместо этого адресуйте его статически, используя имя класса.

Изменить: вот простая демонстрация:

public final class CostTest
{
    private static int cost;

    public static void main(String[] args)
    {
        CostTest costTest;

        System.out.print("initial static cost value: ");
        System.out.println(CostTest.cost);

        costTest = new CostTest(17);

        System.out.print("static cost value: ");
        System.out.println(CostTest.cost);

        System.out.print("static cost value via instance variable: ");
        System.out.println(costTest.cost);
    }

    public CostTest(int cost)
    {
        CostTest.cost = cost;
    }
}

Когда вы поместите это в ecliipse, вы должны увидеть предупреждение в строке System.out.println(costTest.cost);, в котором говорится что-то вроде «Статическое поле CostTest.cost должно быть доступно статическим способом».

person DwB    schedule 19.10.2011

Единственная проблема здесь, если задействовано несколько ClassLoaders. В этом случае может быть экземпляр данного класса в контексте каждого ClassLoader, который затем будет иметь отдельный набор связанных с ним статических полей. Большинство, если не все, контейнеры сервлетов и J2EE используют несколько ClassLoaders, обычно по одному на каждое веб-приложение.

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

Посмотрите это описание для примера: http://vanillajava.blogspot.com/2011/07/java-secret-loading-and-unloading.html

person creechy    schedule 19.10.2011

Несколько переменных Car.cost здесь НЕ МОЖЕТ существовать, потому что Car.cost доступен из каждого класса, загруженного в путь к классам (поскольку он является общедоступным и статическим одновременно).

Когда что-то является «общедоступным статическим» в языках OO, это означает, что его можно рассматривать как глобальную переменную в языках процедур. Это почти то же самое.

Итак, в заключение: экземпляр переменной Car.cost — это всего лишь ОДИН экземпляр для жизненного цикла программы.

Удачи !

person Konstantin Yovkov    schedule 19.10.2011