Могут ли существовать две копии переменной класса? - PullRequest
1 голос
/ 19 октября 2011

У меня есть класс 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);      
}

Ответы [ 5 ]

6 голосов
/ 19 октября 2011

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

Как знамя, это не будет делать то, что вы думаете:

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

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

3 голосов
/ 19 октября 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 должно быть доступно статическим способом».

1 голос
/ 19 октября 2011

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

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

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

1 голос
/ 19 октября 2011

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

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

0 голосов
/ 19 октября 2011

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

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

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

Удачи!

...