Java中私有静态变量的用途是什么?


156

如果将变量声明为public static varName;,则可以从任意位置访问它ClassName.varName。我还知道,静态成员由类的所有实例共享,并且不在每个实例中重新分配。

声明变量与声明变量有private static varName;什么不同private varName;吗?

在这两种情况下,都不能以任何其他类ClassName.varNameClassInstance.varName任何其他类的形式对其进行访问。

将变量声明为静态变量是否赋予它其他特殊属性?


5
Java变量名称不能包含破折号(-)。
Martijn Courteaux'9

Answers:


127

当然,可以将其作为ClassName.var_name,但只能从定义它的类内部进行访问-这是因为它被定义为private

public staticprivate static变量通常用于常量。例如,许多人不喜欢在代码中“硬编码”常量。他们喜欢使用有意义的名称制作一个public staticprivate static变量,并在其代码中使用它,这应该使代码更具可读性。(您还应该创建这样的常量final)。

例如:

public class Example {
    private final static String JDBC_URL = "jdbc:mysql://localhost/shopdb";
    private final static String JDBC_USERNAME = "username";
    private final static String JDBC_PASSWORD = "password";

    public static void main(String[] args) {
        Connection conn = DriverManager.getConnection(JDBC_URL,
                                         JDBC_USERNAME, JDBC_PASSWORD);

        // ...
    }
}

无论你把它public还是private取决于你是否希望变量可见外的类或不。


6
访问as有什么必要ClassName.var_nam?在哪里可以直接访问它:var_nam在课堂上
Vaibhav Jani

12
它不是必要通过类名来访问它,但有些人认为这是良好的作风,从非静态变量区分开来。
杰斯珀,

5
使用静态变量访问它有什么必要,我们可以编写“ private final String JDBC_PASSWORD =“ password”;“ 而不是为此密码字符串使用静态变量。
chaitanya 2014年

48
@chaitanya这是一个常数。为什么要通过使该类成为非静态类而为该类的每个实例提供一个变量副本?
Jesper 2014年

16
static是类级别的变量,这是常见的,并且该类的所有实例都只有一个副本。该规则适用于私人或公共场所。private只是说我不希望外界破坏我的变量值(对于非最终静态变量)。如果一个静态变量是最终的,那么将其公开为无害,因为没有人可以改变其价值。
user1923551 2015年

94

对于类的所有实例,静态变量具有单个值。

如果要进行以下操作:

public class Person
{
    private static int numberOfEyes;
    private String name;
}

然后您想更改您的名字,那很好,我的名字保持不变。但是,如果您想更改它以使您拥有17眼,那么世界上每个人也将拥有17眼。


3
除非您还为私有变量编写访问器方法,否则这不适用于私有静态变量,因为无法从类外部访问它们。
Ganesh Krishnan 2014年

2
@GaneshKrishnan不是正确的,该类的任何实例都可以访问两个变量。自然,您可以期望班级的作者不会做任何愚蠢的事情。同样,通过反射和JNI,所有赌注都关闭了。
TofuBeer

46

私有静态变量的使用方式与私有实例变量的使用方式相同:它们存储状态,状态只能由同一类中的代码访问。变量的可访问性(私有/公共/等)和实例/静态性质完全是正交的概念。

我会避免将静态变量视为在类的“所有实例”之间共享-这表明必须至少存在一个实例才能显示状态。否-静态变量与类型本身关联,而不是与类型的任何实例关联。

因此,任何时候只要您想要某个与类型相关联的状态,而不是任何特定实例,并且想要将该状态保持私有状态(例如,可能允许通过属性进行受控访问),就有一个私有静态变量是有意义的。

顺便说一句,我强烈建议您公开(甚至是非私有)变量的唯一类型是常量-不可变类型的静态最终变量。为了将API和实现分开(除其他外),其他所有事情都应该是私有的。


您能否对一类中的私有静态变量和私有非静态变量访问的区别进行更多说明?
Dharmendra

1
@Dharmendra:我不清楚你的意思。私有部分无关紧要-究竟是什么让您对静态变量和实例变量之间的区别感到困惑?
乔恩·斯基特

当我们在声明了它们的单个类中使用静态和非静态变量时,可访问性有什么区别?
Dharmendra

2
@YogGuru:我没有看到这个问题的相关性。如果希望将其设为私有,则将其设为私有;如果希望将其设为静态,则将其设为静态。它们是正交的。
Jon Skeet

1
@ryvantage:不,一点也不。静态方法可以毫无问题地访问它。
乔恩·斯基特

11

好吧,您是对的,但没有创建类的实例就使用了公共静态变量,但没有使用私有静态变量。它们和我使用私有静态变量的地方之间的主要区别是何时需要在静态函数中使用变量。对于静态函数,您只能使用静态变量,因此您可以将它们设为私有,以免从其他类访问它们。那是我使用private static的唯一情况。

这是一个例子:

Class test {
   public static String name = "AA";
   private static String age;

   public static void setAge(String yourAge) {
       //here if the age variable is not static you will get an error that you cannot access non static variables from static procedures so you have to make it static and private to not be accessed from other classes
       age = yourAge;
   }
}

3
我想我最喜欢这个答案。+1。只有在使用静态方法访问私有变量时,才在私有变量中使用static。
Mukus 2014年

如果没有给类一个适当的名称,您真的不能说这是否是有效的用例。就像,如果该类被称为Person,那可能是一个错误,因为您不能有多个不同年龄的人(如果这是预期的用例)。
DanMan 2015年

我同意@Mukus。这可能是这个问题的唯一真实答案。我认为OP已经了解静态,但是人们似乎想再次解释它。他正在询问一个特定的情况。在静态方法中访问变量的能力是“私有静态”添加的功能。我只想补充一点,它也允许嵌套静态CLASSES访问变量。
Pinkerton

1
那记忆力呢?使用static,您将只为该类创建一个副本,而不是为每个实例创建一个副本。显然,有了一个常数,您只需要一个副本即可。这样可以节省内存吗?

1
我查了一下。我之前的问题的答案是:是的,它可以节省内存
Pinkerton

8

好了,private static变量可用于在该类的实例之间共享数据。没错,虽然我们不能private static使用ClassName.member或那样的结构访问变量,ClassInstance.member但是从该类的方法或该类的实例中始终可以看到该成员。因此,实际上该类的实例将始终能够引用成员。


6

私有静态类变量的用途是什么?

假设您有一本图书馆书籍Class。每次创建新书时,您都希望为其分配一个唯一的ID。一种方法是简单地从0开始并增加ID号。但是,所有其他书籍如何知道最后创建的ID号?简单,将其另存为静态变量。顾客是否需要知道每本书的实际内部编号?否。该信息是私人的。

public class Book {
    private static int numBooks = 0;
    private int id;
    public String name;

    Book(String name) {
        id = numBooks++;
        this.name = name;
    }
}

这是一个人为的示例,但是我敢肯定,您很容易想到一些情况,您希望所有类实例都可以访问应该对所有人保密的公共信息。或即使不能这样做,也是最好的编程习惯,使事情尽可能地私密。如果您不小心使numBooks字段公开,该怎么办,即使Book用户不应该对此做任何事情。这样,某人可以更改书的数量而无需创建新的书。

很偷偷摸摸!


6

声明变量与声明变量有private static varName;什么不同private varName;吗?

是的,两者是不同的。而第一个被称为class variable是因为它为此持有单个值,class而另一个被称为instance variable是因为它可以针对不同的持有不同的值instances(Objects)。第一个在jvm中仅创建一次,而另一个在每个实例中创建一次,即,如果您有10个实例,则private varName;jvm 中将有10个不同的实例。

将变量声明为static其他变量是否具有其他特殊属性?

是的,静态变量与普通实例变量具有某些不同的属性。我已经提到了很少的内容,让我们在这里看到一些:(class variables可以将声明为静态的实例变量)通过使用类名(如)直接访问ClassName.varName。而且该类的任何对象都可以访问和修改其值,这与实例变量仅由其各自的对象访问不同。类变量可以在静态方法中使用。

private static variableJava 中a的用途是什么?

从逻辑上讲,这与第一个给您更多控制权private static variable没有什么不同public static variable。IMO,你可以从字面上代替public static variable通过private static variable与帮助public staticgetter和setter方法。

广泛使用的一个领域private static variable是实现简单Singleton模式,在整个世界中,您将只有该类的单个实例。在这里,static标识符起着至关重要的作用,以使单个实例可以被外界访问(当然,公共静态获取方法也起着主要作用)。

public class Singleton {
    private static Singleton singletonInstance = new Singleton();

    private Singleton(){}

    public static Singleton getInstance(){
        return Singleton.singletonInstance;
    }
}

4

Private关键字将用于类内的变量访问,并且在我们可以在static方法中访问变量的意义上保持静态的意义上,引用变量不能在static方法中访问。


3

另一个角度:

  1. 在运行时,类及其实例是两件事。类信息由该类的所有实例“共享”。
  2. 非静态类变量属于实例,而静态变量属于类。
  3. 就像实例变量可以是私有或公用一样,静态变量也可以是私有或公用。

1

在静态方法中使用变量时,例如,变量也必须是静态的:

private static int a=0;  
public static void testMethod() {  
        a=1;  
}

3
好吧,除非为您的方法提供对课程实例的引用。
乔恩·斯基特


1

对于某些人来说,如果他们以几种不同的语言看到它,则更有意义,因此我在页面上用Java和PHP编写了示例,向我解释了其中一些修饰符。您可能不正确地考虑了这一点。

如果下面没有意义,您应该看一下我的示例。转到此处http://www.siteconsortium.com/h/D0000D.php

最重要的是,它实际上与它所说的完全一样。这是一个私有的静态成员变量。例如,如果您想创建一个Singleton对象,为什么要使SingletonExample.instance变量成为公共变量。如果您做了一个使用该类的人,则很容易覆盖该值。

仅此而已。

    公共类SingletonExample {
      私有静态SingletonExample实例= null;
      private static int值= 0;
      私人SingletonExample(){
        ++ this.value;
      }
      公共静态SingletonExample getInstance(){
        if(instance!= null)
        返回实例;
        同步(SingletonExample.class){
        实例=新的SingletonExample();
        返回实例;
        }
      }
      公共无效printValue(){
        System.out.print(this.value);
      }

      公共静态void main(String [] args){
        SingletonExample实例= getInstance();
        instance.printValue();
        实例= getInstance();
        instance.printValue();
         }
    }


1

如果在类中使用私有静态变量,则类中的“静态内部”类可以访问您的变量。这对于上下文安全性是非常好的。


0

如果将变量定义为公共静态变量,则可以从任何类中通过其类名对其进行访问。

通常,将函数定义为公共静态函数,只需调用实现类名即可对其进行访问。

一个很好的例子是sleep()Thread类中的方法

Thread.sleep(2500);

如果将变量定义为私有静态,则只能在该类中访问它,因此不需要任何类名,或者您仍可以使用类名(由您自己决定)。private var_name和private静态var_name之间的区别在于,私有静态变量只能由该类的静态方法访问,而私有变量可以由该类的任何方法访问(静态方法除外)

一个很好的例子是在定义数据库连接或常量时需要将变量声明为private static。

另一个常见的例子是

private static int numberOfCars=10;

public static int returnNumber(){

return numberOfCars;

}

0

我是Java的新手,但是正如我假设许多人所做的那样,我使用静态变量的一种方法是计算类的实例数。例如:

public Class Company {
    private static int numCompanies;

    public static int getNumCompanies(){
        return numCompanies;
    }
}

然后您可以sysout:

Company.getNumCompanies();

您还可以从该类的每个实例访问numCompanies(我不完全了解),但是它不会以“静态方式”进行。我不知道这是否是最佳做法,但这对我来说很有意义。


0

*)如果一个变量被声明为私有变量,那么它在类之外是不可见的,这被称为数据隐藏。

*)如果一个变量被声明为静态的,那么该变量的值在所有实例中都是相同的,我们不需要创建一个对象来调用该变量,我们可以简单地调用该变量

classname.variablename;


0

私有静态变量也将在子类中共享。如果您在一个子类中进行了更改,而另一子类将获得更改后的值,则在这种情况下,它可能不是您期望的。

public class PrivateStatic {

private static int var = 10;
public void setVar(int newVal) {
    var = newVal;
}

public int getVar() {
    return var;
}

public static void main(String... args) {
    PrivateStatic p1 = new Sub1();
    System.out.println(PrivateStatic.var);
    p1.setVar(200);

    PrivateStatic p2 = new Sub2();
    System.out.println(p2.getVar());
}
}


class Sub1 extends PrivateStatic {

}

class Sub2 extends PrivateStatic {
}

0

ThreadLocal变量通常实现为private static。这样,它们就不会绑定到该类,并且每个线程对自己的“ ThreadLocal”对象都有自己的引用。


3
我不明白这个答案。你什么意思?
H.Rabiee

-1

在下面的示例中,eye由PersonB更改,而leg保持不变。这是因为私有变量将自身复制到方法中,因此其原始值保持不变。而私有静态值只有一个副本可供所有方法共享,因此编辑其值将更改其原始值。

public class test {
private static int eye=2;
private int leg=3;

public test (int eyes, int legs){
    eye = eyes;
    leg=leg;
}

public test (){
}

public void print(){
    System.out.println(eye);
    System.out.println(leg);
}

public static void main(String[] args){
    test PersonA = new test();      
    test PersonB = new test(14,8);
    PersonA.print();    
}

}

> 14 3

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.