可以存在两个类变量副本吗?

时间:2011-10-19 16:02:32

标签: java static-members

我有一个类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 个答案:

答案 0 :(得分:6)

每个加载的类只有一个静态cost变量的实例。但请注意,根据类加载器的不同,可能会多次加载一个类。

作为旁注,这不符合您的想法:

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

在这里,您可以将参数分配给自身(如果您将参数设置为最终,则应该得到编译器错误),而不是静态变量的参数。这也称为阴影和不良做法。

答案 1 :(得分:3)

构造函数中的本地范围成本(参数)隐藏了类范围成本(静态)。 将构造函数更改为:

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”。

答案 2 :(得分:1)

通过将cost字段指定为static,您只会说该变量只有一个共享实例,而不管创建了多少个Car类(在一个进程中)。是的,这些实例中的任何一个都能够修改该单个共享字段,并且由于您将其公开,因此任何其他有权访问Car类的客户端代码也是如此。 (可能使用相同类的其他进程将拥有自己的静态类成员副本,并且无法跨过程边界“看到”。)

从语义上讲,如果我推断汽车的含义并且成本正确,你不想使用静态,除非你希望你的所有汽车都花费相同的成本。在现实世界中,由于装饰,选择等原因,即使在同一车型的相同型号之间,汽车的成本也是高度可变的属性。

答案 3 :(得分:1)

这里唯一的问题是如果涉及多个ClassLoaders。在这种情况下,在每个ClassLoader的上下文中可以存在给定类的实例,然后该实例将具有与其关联的单独的一组静态字段。大多数,如果不是全部,Servlet& J2EE容器使用多个ClassLoaders,通常每个web-app一个。

ClassLoaders通常是分层的,因此您可以访问从父ClassLoader加载的类。通过这种方式,如果您确实需要跨多个Web应用程序的全局单例,您通常会尝试将单例加载到根ClassLoader中,以便可以在任何地方访问它。

查看此说明以获取示例:http://vanillajava.blogspot.com/2011/07/java-secret-loading-and-unloading.html

答案 4 :(得分:0)

此处存在多个Car.cost变量 CAN NOT ,因为Car.cost可以从类路径中加载的每个类访问(因为它同时是公共的和静态的)。

当OO语言中的某些东西是“公共静态”时,这意味着它可以被视为过程语言中的全局变量。它几乎是一样的。

因此,总而言之,Car.cost变量的实例在程序的生命周期中只是一个。

祝你好运!