静态与实例变量:差异?

时间:2014-01-18 13:12:34

标签: java class instance-variables static-variables

静态变量和实例变量之间有什么区别。以下句子是我无法得到的:

  

在某些情况下,只有一个特定变量的副本应由类的所有对象共享 - 这里使用静态变量。
  静态变量表示类范围信息。类的所有对象共享相同的数据。

我认为实例变量是在类宽范围内使用的,而静态变量只在自己的方法中有范围?

9 个答案:

答案 0 :(得分:20)

在类属性的上下文中,static具有不同的含义。如果您有以下字段:

private static int sharedAttribute;

然后,该类的每个实例将共享相同的变量,因此如果您在一个实例中更改它,则更改将反映在所有实例中,在变更之前或之后创建。

如上所述,您可能会理解在许多情况下这很糟糕,因为它很容易变成不良的副作用:更改对象a也会影响b,您可能最终想知道为什么b因没有明显原因而改变。无论如何,有些情况下这种行为是绝对可取的:

  1. 类常量:因为它们是const,所有类访问相同的值都不会有害,因为没有人可以改变它。如果你有很多的那个类的实例,它们也可以节省内存。但不确定并发访问权限。
  2. 要共享变量,例如参考计数器& co。
  3. static vars在你的程序启动之前被实例化,所以如果你有太多这些vars,你可以减慢启动速度。

    static方法只能访问static个属性,但在尝试之前请三思。

    经验法则:不要使用static,除非有必要且你知道自己在做什么,或者你宣布一个类不变。

答案 1 :(得分:10)

假设有一个测试类:

class Test{
public static int a = 5;
public int b = 10;
}
// here t1 and t2 will have a separate copy of b
// while they will have same copy of a.
Test t1 = new test(); 
Test t2 = new test();

您可以使用类名称

来访问静态变量
Test.a = 1//some value But you can not access instance variable like this
System.out.println(t1.a);
System.out.println(t2.a);

在这两种情况下,输出将是1,因为它是所有测试类实例的共享。 而实例变量每个都有b的单独副本(实例变量) 所以

 t1.b = 15 // will not be reflected in t2.
 System.out.println(t1.b); // this will print 15
 System.out.println(t2.b); / this will still print 10; 

希望能解释您的疑问。

答案 2 :(得分:8)

实例变量

这些变量属于类的实例,因此属于对象。并且该类(对象)的每个实例都拥有该变量的副本。对变量所做的更改不会反映在该类的其他实例中。

public class Product {
    public int barcode;
}

类变量

这些也称为静态成员变量,并且只有该变量的一个副本与该类的所有实例共享。如果对该变量进行了更改,则所有其他实例都将看到更改的效果。

public class Product {
    public static int barcode;
}

完整示例:

实例变量

public class Main {
    public static void main(String[] args) {

        Product prod1 = new Product();
        prod1.barcode = 123456;

        Product prod2 = new Product();
        prod2.barcode = 987654;

        System.out.println(prod1.barcode);
        System.out.println(prod2.barcode);
    }
}

public class Product {
    public int barcode;
}

输出将是:

  

123456
  987654

现在,通过将实例变量设置为静态来将其更改为类变量:

类变量

public class Main {
    public static void main(String[] args) {

        Product prod1 = new Product();
        prod1.setBarcode(123456);
        Product prod2 = new Product();
        prod2.setBarcode(987654);

        System.out.println(prod1.getBarcode());
        System.out.println(prod2.getBarcode());
    }
}

public class Product {
    public static int barcode;

    public int getBarcode() {
        return barcode;
    }

    public void setBarcode(int value){
        barcode = value;
    }
}

我使用非静态方法来获取和设置条形码的值,以便能够从对象而不是从类中调用它。
输出将如下:

  

987654
  987654

答案 3 :(得分:4)

类变量只有一个由类的所有不同对象共享的副本,而每个对象都有自己的实例变量的个人副本。因此,跨不同对象的实例变量可以具有不同的值,而跨不同对象的类变量只能有一个值。

答案 4 :(得分:1)

静态(类)变量和实例变量都是成员变量,因为它们都与特定的类相关联,但它们之间的区别是类变量只有一个由类的所有不同对象共享的副本,而每个对象都有自己的实例变量的个人副本。因此,跨不同对象的实例变量可以具有不同的值,而跨不同对象的类变量只能有一个值。

答案 5 :(得分:1)

实例变量包含必须由多个方法,构造函数或块引用的值,或者必须在整个类中存在的对象状态的基本部分。静态变量只是每个类的每个类变量的一个副本,无论从中创建了多少个对象。

答案 6 :(得分:1)

假设我们创建一个静态变量K,并在主函数中创建三个对象: ob1 ob2 ob3; 所有这些对象的变量K可以具有相同的值。相反,如果变量K是实例变量,则其可以具有不同的值,例如: ob1.k ob2.k ob3.k

答案 7 :(得分:0)

我认为您正在考虑static关键字的C / C ++定义。在那里,static关键字有很多用途。在Java中,您的帖子中描述了静态关键字的功能。无论如何,你可以自己尝试一下:

public class Test_Static{
    static int x;
    public static void main(String[] argv){
        Test_Static a = new Test_Static();
        Test_Static b = new Test_Static();
        a.x = 1; // This will give an error, but still compile.
        b.x = 2;
        System.out.println(a.x); // Should print 2
    }
}

和非静态变量类似:

public class Test_NonStatic{
     int x;
     public static void main(String [] argv){
         Test_NonStatic a = new Test_NonStatic();
         Test_NonStatic b = new Test_NonStatic();
         a.x = 1;
         b.x = 2;
         System.out.println(a.x); // Should print 1.
     }
}

答案 8 :(得分:0)

考虑一个类MyClass,它有一个静态成员和一个非静态成员:

public class MyClass {
    public static int STATICVARIABLE = 0;
    public int nonStaticVariable = 0;
}

现在,让我们创建一个main()来创建几个实例:

public class AnotherClass{  
    public static void main(String[] args) {    
        // Create two instances of MyClass
        MyClass obj1  = new MyClass();
        MyClass obj2  = new MyClass();
        obj1.nonStaticVariable = 30;  // Setting value for nonstatic varibale
        obj1.STATICVARIABLE = 40; //Setting value for static variable       
        obj2.nonStaticVariable = 50;
        obj2.STATICVARIABLE = 60;

        // Print the values actually set for static and non-static variables.
        System.out.println(obj1.STATICVARIABLE);
        System.out.println(obj1.nonStaticVariable);
        System.out.println(obj2.STATICVARIABLE);
        System.out.println(obj2.nonStaticVariable);
    }
}

结果:

60
30
60
50

现在,您可以看到打印60两个时间的静态变量的值,因为obj1obj2都指的是同一个变量。使用非静态变量,输出不同,因为创建时每个对象都保留自己的非静态变量副本;对它们所做的更改不会影响另一个对象创建的变量的另一个副本。