代码之家  ›  专栏  ›  技术社区  ›  Anish Shanbhag

对列表中变量的引用[重复]

  •  4
  • Anish Shanbhag  · 技术社区  · 6 年前

    这个问题已经有了答案:

    对不起,我的题目含糊不清,希望我能在这里把我的问题弄清楚。

    我有一些二维的 List<List<Double>> myList 每个子列表包含两个项:一个显式 double ,例如 2.0 ,还有一个 双重的 变量。本质上,我想做的不是在列表中存储一些常量值,而是存储对变量的引用,因为变量将在程序的其他部分发生更改,并且列表应该反映出这一点。下面是我想要做的事情的一个非常简单的版本:

    import java.util.Arrays;
    import java.util.List;
    
    public class Example {
    
        static double apples = 10.0;
    
        static double oranges = 5.0;
    
        static List<List<Double>> myList = Arrays.asList((Arrays.asList(2.0, apples)), (Arrays.asList(2.0, oranges)));
    
        public static void main(String[] args) {
    
            apples += 3;
    
            oranges += 3;
    
            for (List<Double> list : myList) {
    
                // list.get(1) -= list.get(0);
    
                System.out.println(list.get(1) - list.get(0));
    
            }
    
        }
    
    }
    

    程序输出如下:

    8.0
    3.0
    

    但是,它应该是:

    11.0
    6.0
    

    因为 apples oranges 都增加了3个。此外,注意注释掉的行 list.get(1) -= list.get(0); . 我最终想要做的是减少 list.get(1) 按指定金额 list.get(0) . 但是,当我取消对此行的注释时,我得到:

    Error:(20, 25) java: unexpected type
      required: variable
      found:    value
    

    我认为这两个问题都是由于 苹果 橘子 作为常量值存储在列表中,而不是对实际变量本身的引用。这是因为我用 Arrays.asList() 创建 myList ?或者是我定义的问题 List<List<Double>> ?或者是其他的问题?

    谢谢你的帮助。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Travis    6 年前

    您遇到的主要问题是易变性和引用。

    对象变量有一个引用作为其值,然后根据需要取消引用。赋值运算符更改引用,而不是其基础值。Java双包装器类是不可变的,因此不能更改它的值。

    apples += 3;
    oranges +=3;
    

    苹果/桔子指向的对象的值不加3,而是创建一个新的双对象,其值3大于苹果/桔子。然后,苹果/桔子被分配到各自对象的引用。您的列表仍然具有对旧对象的引用。

    正如Martn Zaragoza建议的那样,您可以创建一个包装类,它是一个非常基本的类,具有一个公共成员,并且只有一个构造函数,如下所示:

    public class MutableDouble {
        public double value
        public MutableDouble(double iV){
            this.value = iV
        }
    }
    

    然后可以将苹果和桔子指定为可变的双值,并更改apples.value和oranges.value字段。

    您也可以使用原子参考,正如下面评论中stephane k.建议的那样。

    include java.util.concurrent.atomic.AtomicReference;
    

    然后:

    AtomicReference apples = new AtomicReference(2.0);
    System.out.println(apples);
    apples.set((double)apples.get() + 5.0);
    System.out.println(apples);
    

    输出:

    2.0
    7.0
    

    如果更改基础对象,而不是将变量重新分配给新对象,则引用该对象的代码的其他区域将看到更改。

    关于减法的问题,您试图为一个值赋值。get(1)返回一个double,所以你基本上是说 10.0 = 8.0 . 试试这个:

    list.set(1, list.get(1) - list.set(0));
    

    这将把减法的值赋给列表中索引1处的项。

        2
  •  1
  •   Фарид Азаев    6 年前

    理解的例子

    public static void main( String[] args ) {
        class testClass {
            int b;
    
            @Override
            public String toString() {
                return "testClass{" +
                        "b=" + b +
                        '}';
            }
        }
        List<Double> d = new ArrayList<>();
        Double dd = new Double("2.0");
        d.add(dd);
        System.out.println(d.toString());
        dd = 3.0;
        System.out.println(d.toString());
    
    
        List<testClass> tList = new ArrayList<>();
        testClass t = new testClass();
        t.b =1;
        tList.add(t);
        System.out.println(tList.toString());
        t.b=2;
        System.out.println(tList.toString());
    }
    

    输出

    [2.0]
    [2.0]
    [testClass{b=1}]
    [testClass{b=2}]