我有一个类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);
}
答案 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变量的实例在程序的生命周期中只是一个。
祝你好运!