如何将此类转换为不可变?

时间:2016-02-07 11:11:20

标签: java class arraylist immutability

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

功能getArray(Box b)将创建Box个对象的ArrayList。

    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 个答案:

答案 0 :(得分:0)

这将是一个不可变的:

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,因此您无法将其子类化。

答案 1 :(得分:0)

简而言之,不可变对象是一个对象,其状态在创建后无法修改。你的不可变Box对象看起来像这样:

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只分配了一次。没有setter,因为Box的不变性意味着它的状态(包括变量ab)在其生命周期内不会改变。

finala前面的b关键字意味着您必须将其分配一次。除非你特别需要它们,否则所有变量都是最终的,这被认为是一种好的做法。但对于一个不可变的对象,它是必不可少的。

您使用的是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实例。