首页 文章

私有最终静态属性vs私有最终属性

提问于
浏览
263

在Java中,有什么区别:

private final static int NUMBER = 10;

private final int NUMBER = 10;

两者都是 privatefinal ,区别在于 static 属性 .

什么更好?为什么?

20 回答

  • 1

    静态的是所有类实例和类本身的相同成员 .
    非静态是每个实例(对象)的一个,所以在 your exact case 中如果你放置静态则浪费内存 .

  • 0

    如果您将此变量标记为静态,那么如您所知,您将需要静态方法再次访问这些值,如果您已经考虑过仅在静态方法中使用这些变量,这将非常有用 . 如果是这样那么这将是最好的 .

    然而,您可以将变量现在设为公开,因为没有人可以像“System.out”那样修改它,它又取决于您的意图和您想要实现的目标 .

  • 0

    通常, static 表示“与类型本身相关联,而不是类型的实例” .

    这意味着您可以引用静态变量而无需创建该类型的实例,并且引用该变量的任何代码都指的是完全相同的数据 . 将其与实例变量进行比较:在这种情况下,每个类的实例都有一个独立的变量版本 . 例如:

    Test x = new Test();
    Test y = new Test();
    x.instanceVariable = 10;
    y.instanceVariable = 20;
    System.out.println(x.instanceVariable);
    

    打印出10: y.instanceVariablex.instanceVariable 是分开的,因为 xy 指的是不同的对象 .

    您可以通过引用引用静态成员,但这样做是个坏主意 . 如果我们这样做:

    Test x = new Test();
    Test y = new Test();
    x.staticVariable = 10;
    y.staticVariable = 20;
    System.out.println(x.staticVariable);
    

    然后打印出20 - 只有一个变量,而不是每个实例一个变量 . 把它写成以下内容会更清楚:

    Test x = new Test();
    Test y = new Test();
    Test.staticVariable = 10;
    Test.staticVariable = 20;
    System.out.println(Test.staticVariable);
    

    这使得行为更加明显 . 现代IDE通常会建议将第二个列表更改为第三个 .

    没有理由有这样的声明

    private final int NUMBER = 10;
    

    如果它不能改变,那么每个实例只有一个副本是没有意义的 .

  • 2

    对于 final ,初始化时可以在运行时为其分配不同的值 . 例如

    Class Test{
      public final int a;
    }
    
    Test t1  = new Test();
    t1.a = 10;
    Test t2  = new Test();
    t2.a = 20; //fixed
    

    因此每个实例具有不同的字段 a 的值 .

    对于 static final ,所有实例共享相同的值,并且在首次初始化后不能更改 .

    Class TestStatic{
          public static final int a;
    }
    
    TestStatic t1  = new TestStatic();
    t1.a = 10;
    TestStatic t2  = new TestStatic();
    t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.
    
  • 12

    static 变量在应用程序的整个生命周期内保留在内存中,并在类加载期间初始化 . 每次构造 new 对象时,都会初始化非 static 变量 . 通常最好使用:

    private static final int NUMBER = 10;
    

    为什么?这减少了每个实例的内存占用量 . 它可能也有利于缓存命中 . 它只是有意义: static 应该用于某种类型的所有实例(a.k.a.对象)共享的东西(a.k.a . class ) .

  • 1

    static表示“与 class 相关”;没有它,变量与类的每个实例相关联 . 如果它是静态的,那意味着你只有一个在内存中;如果没有,您将为您创建的每个实例分配一个 . static表示只要加载类,变量就会保留在内存中;没有它,变量可以在其实例时被gc'd .

  • 22

    阅读答案我发现没有真正的测试真正达到目的 . 这是我的2美分:

    public class ConstTest
    {
    
        private final int         value             = 10;
        private static final int  valueStatic       = 20;
        private final File        valueObject       = new File("");
        private static final File valueObjectStatic = new File("");
    
        public void printAddresses() {
    
    
            System.out.println("final int address " +
                    ObjectUtils.identityToString(value));
            System.out.println("final static int address " +
                    ObjectUtils.identityToString(valueStatic));
            System.out.println("final file address " + 
                    ObjectUtils.identityToString(valueObject));
            System.out.println("final static file address " + 
                    ObjectUtils.identityToString(valueObjectStatic));
        }
    
    
        public static void main(final String args[]) {
    
    
            final ConstTest firstObj = new ConstTest();
            final ConstTest sndObj = new ConstTest();
    
            firstObj.printAdresses();
            sndObj.printAdresses();
        }
    
    }
    

    第一个对象的结果:

    final int address java.lang.Integer@6d9efb05
    final static int address java.lang.Integer@60723d7c
    final file address java.io.File@6c22c95b
    final static file address java.io.File@5fd1acd3
    

    第二个对象的结果:

    final int address java.lang.Integer@6d9efb05
    final static int address java.lang.Integer@60723d7c
    final file address java.io.File@3ea981ca
    final static file address java.io.File@5fd1acd3
    

    结论:

    我认为java会在原始类型和其他类型之间产生差异 . Java中的原始类型总是“缓存”,对于字符串文字(不是新的String对象)也是如此,因此静态和非静态成员之间没有区别 .

    但是,如果非静态成员不是基本类型的实例,则存在重复内存 .

    将valueStatic的值更改为10甚至会更进一步,因为Java将为两个int变量提供相同的地址 .

  • 9

    让我们说如果该类不会有多个实例,那么哪一个需要更多的内存:

    private static final int ID = 250;或私人最终int ID = 250;

    我已经知道静态将引用类型,内存中只有一个副本,非静态将位于每个实例变量的新内存位置 . 但是在内部,如果我们只是比较同一个类的1个实例(即不会创建多于1个实例),那么1个静态最终变量使用的空间是否有任何开销?

  • 0

    虽然其他答案似乎很清楚,通常没有理由使用非静态常量,但我找不到任何人指出可能在其常量变量上有不同值的各种实例 .

    请考虑以下示例:

    public class TestClass {
        private final static double NUMBER = Math.random();
    
        public TestClass () {
            System.out.println(NUMBER);
        }
    }
    

    创建三个TestClass实例将打印相同的随机值三次,因为只生成一个值并将其存储到静态常量中 .

    但是,在尝试以下示例时:

    public class TestClass {
        private final double NUMBER = Math.random();
    
        public TestClass () {
            System.out.println(NUMBER);
        }
    }
    

    创建三个TestClass实例现在将打印三个不同的随机值,因为每个实例都有自己的随机生成的常量值 .

    我想不出任何情况,在不同的实例上有不同的常量值是非常有用的,但我希望这有助于指出静态和非静态终结之间存在明显的区别 .

  • 0

    正如Jon所说,静态变量(也称为类变量)是一个跨类实例存在的变量 .

    我找到了一个这样的例子here

    public class StaticVariable
    {
      static int noOfInstances;
      StaticVariable()
      {
        noOfInstances++;
      }
      public static void main(String[] args)
      {
        StaticVariable sv1 = new StaticVariable();
        System.out.println("No. of instances for sv1 : " + sv1.noOfInstances);
    
        StaticVariable sv2 = new StaticVariable();
        System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
        System.out.println("No. of instances for st2 : "  + sv2.noOfInstances);
    
        StaticVariable sv3 = new StaticVariable();
        System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
        System.out.println("No. of instances for sv2 : "  + sv2.noOfInstances);
        System.out.println("No. of instances for sv3 : "  + sv3.noOfInstances);
      }
    }
    

    该计划的产出如下:

    正如我们在本例中所见,每个对象都有自己的类变量副本 .

    C:\java>java StaticVariable
    No. of instances for sv1 : 1
    No. of instances for sv1 : 2
    No. of instances for st2 : 2
    No. of instances for sv1 : 3
    No. of instances for sv2 : 3
    No. of instances for sv3 : 3
    
  • 2

    从我所做的测试来看,静态最终变量与之不同最终(非静态)变量!最终(非静态)变量可能因对象而异!但这只是在构造函数中进行初始化的时候! (如果没有从构造函数初始化它,那么它只是浪费内存,因为它为每个创建的无法更改的对象创建最终变量 . )

    例如:

    class A
    {
        final int f;
        static final int sf = 5;
    
        A(int num)
        {
            this.f = num;
        }
    
        void show()
        {
            System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf);
        }
    
        public static void main(String[] args)
        {
            A ob1 = new A(14);
            ob1.show();
    
            A ob2 = new A(21);
            ob2.show();
    
        }
    }
    

    屏幕上显示的是:

    关于对象:A @ addbf1决赛:14静态决赛:5

    关于对象:@ 530daa决赛:21场决赛:5

    匿名的第一年IT学生,希腊

  • -1

    对于Jon的回答,如果你使用静态final,它将表现为一种"definition" . 一旦你编译了使用它的类,它就会被编译的.class文件烧掉 . 检查我的帖子here .

    为了您的主要目标:如果您在类的不同实例中不使用NUMBER,我建议使用final和static . (你必须记住不要复制已编译的类文件,而不考虑我的案例研究所描述的可能的麻烦 . 大多数情况都不会发生,不要担心:))

    为了向您展示如何在实例中使用不同的值,请检查以下代码:

    public class JustFinalAttr {
      public final int Number;
    
      public JustFinalAttr(int a){
        Number=a;
      }
    }
    
    ...System.out.println(new JustFinalAttr(4).Number);
    
  • 281

    这是我的两分钱:

    final           String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
    final   static  String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
    

    例:

    package test;
    
    public class Test {
    
        final long OBJECT_ID = new Random().nextLong();
        final static long CLASSS_ID = new Random().nextLong();
    
        public static void main(String[] args) {
            Test[] test = new Test[5];
            for (int i = 0; i < test.length; i++){
                test[i] = new Test();
                System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value
                System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different
            }
        }
    }
    

    关键是变量和函数可以返回不同的值 . 因此可以为最终变量分配不同的值 .

  • 1

    非常少,而且是静态的

    没有太大的区别,因为它们都是常数 . 对于大多数类数据对象,静态意味着与类本身相关联的东西,无论使用new创建了多少个对象,只有一个副本 .

    由于它是一个常量,它实际上可能不会存储在类或实例中,但编译器仍然不允许您从静态方法访问实例对象,即使它知道它们将是什么 . 如果你没有使它静态,反射API的存在也可能需要一些毫无意义的工作 .

  • 0

    由于类中的变量在同一命令中被声明为最终AND初始化,因此绝对没有理由不将其声明为静态,因为无论实例如何它都具有相同的值 . 因此,所有实例都可以为一个值共享相同的内存地址,从而无需为每个实例创建一个新变量并通过共享一个公共地址来节省内存,从而节省了处理时间 .

  • 15

    private static final将被视为常量,并且只能在此类中访问常量 . 由于包含关键字static,因此该值对于类的所有对象都是常量 .

    private final变量值将类似于每个对象的常量 .

    您可以参考java.lang.String或查找下面的示例 .

    public final class Foo
    {
    
        private final int i;
        private static final int j=20;
    
        public Foo(int val){
            this.i=val;
        }
    
        public static void main(String[] args) {
            Foo foo1= new Foo(10);
    
            Foo foo2= new Foo(40);
    
            System.out.println(foo1.i);
            System.out.println(foo2.i);
            System.out.println(check.j);
        }
    }
    

    //输出:

    10
    40
    20
    
  • 2

    静态变量属于类(这意味着所有对象共享该变量) . 非静态变量属于每个对象 .

    public class ExperimentFinal {
    
    private final int a;
    private static final int b = 999; 
    
    public ExperimentFinal(int a) {
        super();
        this.a = a;
    }
    public int getA() {
        return a;
    }
    public int getB() {
        return b;
    }
    public void print(int a, int b) {
        System.out.println("final int: " + a + " \nstatic final int: " + b);
    }
    public static void main(String[] args) {
        ExperimentFinal test = new ExperimentFinal(9);
        test.print(test.getA(), test.getB());
    } }
    

    正如您在上面的示例中所看到的,对于“final int”,我们可以为类的每个实例(对象)分配我们的变量,但是对于“static final int”,我们应该在类中分配一个变量(静态变量属于该类) ) .

  • 2

    另一个简单的例子来理解静态,静态final,final变量的用法 . 代码注释是正确的说明 .

    public class City {
    
        // base price that is always same for all objects[For all cities].
        private static double iphone_base_price = 10000;
    
        // this is total price = iphone_base_price+iphone_diff;
        private double iphone_citi_price;
    
        // extra price added to iphone_base_price. It is constant per city. Every
        // city has its own difference defined,
        private final double iphone_diff;
    
        private String cityName = "";
    
        // static final will be accessible everywhere within the class but cant be
        // changed once initialized.
        private static final String countryName = "India";
    
        public City(String cityName, double iphone_diff) {
            super();
            this.iphone_diff = iphone_diff;
            iphone_citi_price = iphone_base_price + iphone_diff;
            this.cityName = cityName;
    
        }
    
        /**
         * get phone price
         * 
         * @return
         */
        private double getPrice() {
    
            return iphone_citi_price;
        }
    
        /**
         * Get city name
         * 
         * @return
         */
        private String getCityName() {
    
            return cityName;
        }
    
        public static void main(String[] args) {
    
            // 300 is the
            City newyork = new City("Newyork", 300);
            System.out.println(newyork.getPrice() + "  " + newyork.getCityName());
    
            City california = new City("California", 800);
            System.out.println(california.getPrice() + "  " + california.getCityName());
    
            // We cant write below statement as a final variable can not be
            // reassigned
            // california.iphone_diff=1000; //************************
    
            // base price is defined for a class and not per instances.
            // For any number of object creation, static variable's value would be the same
            // for all instances until and unless changed.
            // Also it is accessible anywhere inside a class.
            iphone_base_price = 9000;
    
            City delhi = new City("delhi", 400);
            System.out.println(delhi.getPrice() + "  " + delhi.getCityName());
    
            City moscow = new City("delhi", 500);
            System.out.println(moscow.getPrice() + "  " + moscow.getCityName());
    
            // Here countryName is accessible as it is static but we can not change it as it is final as well. 
            //Something are meant to be accessible with no permission to modify it. 
            //Try un-commenting below statements
            System.out.println(countryName);
    
            // countryName="INDIA";
            // System.out.println(countryName);
    
        }
    
    }
    
  • 37

    如果使用static,变量的值在所有实例中都是相同的,如果在一个实例中更改,其他实例也会更改 .

  • 0

    这可能有所帮助

    public class LengthDemo {
    public static void main(String[] args) {
        Rectangle box = new Rectangle();
        System.out.println("Sending the value 10.0 "
                + "to the setLength method.");
        box.setLength(10.0);
        System.out.println("Done.");
        }
    }
    

相关问题