【问题标题】:private static field Java私有静态字段 Java
【发布时间】:2020-11-12 09:55:41
【问题描述】:

我被问到以下问题:

假设Java中类A的所有实例字段和所有实例方法都是私有的,下列哪项是正确的:

  1. A 是不可变的
  2. A 不一定是不可变的,因为它可能扩展了一个不可变的类
  3. A 不一定是不可变的,因为您可以通过静态方法更改其字段

我以为正确答案是 1,但结果 2 和 3 都是正确的,而 1 不是。

如果所有内容都是私有的,您仍然可以修改字段吗?

为什么如果它扩展了一个不可变的类,但仍然拥有私有的所有内容,它现在可能是不可变的?

从静态方法改变其字段是什么意思?

【问题讨论】:

  • 不可变对象是在完全创建后其内部状态保持不变的对象。我们还应该有final 关键字。更多详情请阅读:baeldung.com/java-immutable-object
  • 2.如果它扩展了一个可变类,则它具有 A 声明的私有字段以外的字段。 3. A 中的静态方法可以完全访问 A 中的私有字段,因此它们可能会对其进行变异。
  • 第2点:如果你有public class A extends B,即使A的所有字段和方法都是私有的,你也不知道B声明了哪些字段。 B 可能有非私有字段/公共设置器。这些字段也将属于A(自A extends B),并且可以从类外部修改它们,从而使A 的状态可变。
  • 第3点:如果A内部有public static方法,那么该方法可以访问A的私有字段。如果有人从外部调用静态方法,该方法可能会静音A的私有字段的状态。
  • @ucei static 字段或方法意味着它没有链接到类的特定实例,但它始终与类本身相同(“静态”)。你需要在静态方法中有一个A 的实例,如果你尝试A a = new A(); 然后尝试访问a 的私有字段(比如说a.x),你将能够做到这一点,即使xprivateA

标签: java static field private final


【解决方案1】:

A 可以扩展具有公共字段的类,在这种情况下,尽管 A 本身没有定义任何可变字段,但仍可以修改这些字段,因为它将从其父类继承字段和实例方法。

考虑以下代码:

class Child extends Parent {
    private String name;
}
class Parent {
    public int id;
}
class TestChild {
    public static void main(final String[] args) {
        final Child child = new Child();
        //String s = child.name;<--The field Child.name is not visible
        System.out.println("Previous id: " + child.id);
        child.id = 100;//<--We can modify this because it is defined as public in Parent
        System.out.println("Updated id: " + child.id);
    }
}

output 将是:

Previous id: 0
Updated id: 100

对于下一种情况,问题似乎是指实例方法中的方法,而不是指定是否存在静态方法。公开的静态方法可以在任何地方调用并通过修改静态字段产生副作用,还可以访问A 实例上的私有实例字段,这使得A 不是不可变的。

【讨论】:

    【解决方案2】:

    第 2 点:

    class B {
        public int bValue;
    }
    
    class A extends B {
        private int aValue;
    }
    

    A 的实例不是不可变的,因为它继承了可以更改的 bValue 字段。


    第 3 点:

    class A {
        private int x;
    
        public static void mutate(A a) {
            a.x += 1;
        }
    }
    

    可以通过调用静态方法A.mutate 来改变A 的实例,该方法可以完全访问A 的私有字段。现在的规定,“Java 中 A 类的所有实例方法都是私有的”,不适用于静态方法。

    【讨论】:

    • 对于第 3 点:Assume all fields and all methods of class A in Java are privatemutate 不应该是私有的吗?
    • 要使问题中的第 3 点为真,正如 OP 所说的那样,这必须不适用于静态方法。
    • 是的,似乎 op 遗漏了问题中的某些内容。
    • 原问题说,“所有实例字段和实例方法都是私有的”。这对这个问题有帮助吗?静态方法/字段不算作实例吗? (我编辑了问题)
    • 是的,这是一个重要的区别。静态方法不是实例方法。
    【解决方案3】:

    前面的答案都是对的。关于

    的问题
    1. A 不一定是不可变的,因为您可以通过静态方法更改其字段

    可以这样实现

    public class Test {
    public static void main(String[] args) {
        A a = new A(10);
        System.out.println(a);
        A.mutateObj(20);
        System.out.println(a);
     }
    }
    
    class A {
     private static A a;
     private int x;
    
     A(int x) {
        this.a = this;
        this.x = x;
     }
    
     public static void mutateObj(int b) {
        a.x = b;
     }
    
     @Override
     public String toString() {
        return "A{" +
                "x=" + x +
                '}';
     }
    }
    

    结果 =>

    A{x=10}
    A{x=20}
    

    【讨论】:

      猜你喜欢
      • 2012-09-29
      • 2014-02-11
      • 2014-06-19
      • 1970-01-01
      • 2013-07-14
      • 1970-01-01
      • 2011-03-19
      相关资源
      最近更新 更多