有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将这个类转换为不可变的?

我正在学习不变性,但我不能确切地理解它是如何工作的。所以为了让我理解不变性,我创建了一个测试程序

函数getArray(Box b)将生成Box对象的数组列表

    Expected output:    Actual output:

    Output              Output
    a is 5              a is 5
    b is 10             b is 10

    Output              Output
    a is 0              a is 4
    b is 0              b is 40

    Output              Output
    a is 1              a is 4
    b is 10             b is 40

    Output              Output
    a is 2              a is 4
    b is 20             b is 40

    Output              Output
    a is 3              a is 4
    b is 30             b is 40

    Output              Output
    a is 4              a is 4
    b is 40             b is 40

逻辑:

public class Box {

    static int a;
    static int b;

    public Box() {
        a = 5;
        b = 10;
    }

    public int getA() {
        return a;
    }

    public void setA(int x) {
        a = x;
    }

    public int getB() {

        return b;
    }

    public void setB(int x) {
        b = x;
    }

    public void display() {
        System.out.println("Output");
        System.out.println("a is " + a);
        System.out.println("b is " + b);
        System.out.println();

    }
}

主类

import java.util.ArrayList;

public class Check {

    public static void main(String[] args) {

        Box b = new Box();
        b.display();

        ArrayList<Box> arr2 = new ArrayList<Box>();

        arr2 = getArray(b);

        for (int i = 0; i < arr2.size(); i++) {
            arr2.get(i).display();
        }

    }

    public static ArrayList<Box> getArray(Box b) {

        ArrayList<Box> arr = new ArrayList<Box>();
        for (int i = 0; i < 5; i++) {
            b.setA(i);
            b.setB(i * 10);
            arr.add(b);
        }
        return arr;

    }

}

如何更改逻辑,以获得所需的输出?我们如何决定如何以及在何处编辑代码以确保不变性


共 (2) 个答案

  1. # 1 楼答案

    这将是一个不变的:

    public final class Box {
       final int a;
       final int b;
    
       public Box(int a, int b) {
          this.a = a;
          this.b = b;
       }
    }
    

    然后你的数组方法是:

    public static ArrayList<Box> getArray(Box b) {
    
       ArrayList<Box> arr = new ArrayList<Box> ();
       for(int i =0 ;i <5; i++) {
          arr.add(new Box(i, i*10));
       }
       return arr;
    
    }
    

    数据成员被声明为final,因为它们是不可变的,所以getter没有意义,setter没有意义

    该类被声明为final,因此不能对其进行子类化

  2. # 2 楼答案

    简而言之,不可变对象是一个在创建后状态无法修改的对象。您的不可变框对象如下所示:

    public final class Box {
    
        private final int a;
        private final int b;
    
        public Box(int a, int b) {
            this.a = a;
            this.b = b;
        }
    
        public int getA() {
            return a;
        }
    
        public int getB() {
            return b;
        }
    
        public void display() {
            System.out.println("Output");
            System.out.println("a is " + a);
            System.out.println("b is " + b);
            System.out.println();
        }
    
    }
    

    请注意,在构建Box实例期间,变量ab只分配了一次。没有设置器,因为Box的不变性意味着它的状态(包括变量ab)在其生命周期内不会改变

    ab前面的final关键字意味着必须精确地分配它们一次。实际上,将所有变量设置为最终变量被认为是一种很好的做法,除非你特别需要它们;但对于一个不变的对象来说,这是必不可少的

    您使用的是static关键字。静态与不变性无关。这意味着该变量在Box类的所有实例中共享。在我的示例中,每个Box实例都有自己的ab副本,因为我没有将它们设置为静态

    最后,我将给出一个具有所需输出的主类的示例:

    public class Check {
    
        public static void main(String[] args) {
            final List<Box> arr2 = getArray();
            for (int i = 0; i < arr2.size(); i++) {
                arr2.get(i).display();
            }
        }
    
        public static ArrayList<Box> getArray() {
            final ArrayList<Box> arr = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                final Box box = new Box(i, i * 10);
                arr.add(box);
            }
            return arr;
        }
    
    }
    

    请注意,在循环的每次迭代中都会创建一个新的box实例