【问题标题】:Java: Why does this swap method not work? [duplicate]Java:为什么这种交换方法不起作用? [复制]
【发布时间】:2011-01-03 17:37:52
【问题描述】:

我有以下代码:

public class Main {

    static void swap (Integer x, Integer y) {
        Integer t = x;
        x = y;
        y = t;
    }

    public static void main(String[] args) {
       Integer a = 1;
       Integer b = 2;
       swap(a, b);
       System.out.println("a=" + a + " b=" + b);
    } 
}

我希望它打印 a=2 b=1,但它打印相反。所以显然交换方法不会交换 a 和 b 值。为什么?

【问题讨论】:

  • 请参考按值调用和按引用调用的区别。
  • 在方法 swap 中,您传递的是对象的“值”,而不是对实际对象的引用,无论您在 swap 方法中做什么,都不会影响变量 a 和 b。

标签: java


【解决方案1】:

整数是不可变的——你不能改变它们的值。交换函数内部发生的交换是引用,而不是值。

你需要在一个数组中返回两个引用来实现你想要的

static Integer[] swap(Integer a, Integer b) {
   return new Integer[]{b, a};
}

public static void main(String[] args) {
   Integer a = 1;
   Integer b = 2;

   Integer[] intArray = swap(a, b);

   a = intArray[0];
   b = intArray[1];

   System.out.println("a=" + a + " b=" + b);
} 

如果 Integer 有一个 setValue 方法,你可以这样做。

static void swap(Integer a, Integer b) {
   int temp = a.intValue();
   a.setValue(b.intValue());
   b.setValue(temp);
}

但它没有 - 所以要实现你想要的,返回一个数组。

【讨论】:

  • 整数不变性不是这里的问题。
【解决方案2】:

这与整数的不变性无关;这与Java is Pass-by-Value, Dammit! (不生气,只是文章标题:p)

有关

总结一下:你不能在 Java 中创建一个 swap 方法。您只需要自己进行交换,无论您需要什么;反正这只是三行代码,所以应该不是什么大问题:)

    Thing tmp = a;
    a = b;
    b = tmp;

【讨论】:

  • 为什么投反对票?我是不是误会了什么?
  • 但是如果 Integer 是可变的并且具有例如 setValue 字段,则通过调用 setValue 来交换值将是一个可见的变化。所以它确实与可变性有关,因为你仍然可以有一个 void 方法来实现作者想要的结果。
  • 但是您实际上不会交换整数,这似乎是目标。如果我有一个有两辆车的停车场,然后让第一辆车看起来和第二辆车一模一样,第二辆车和第一辆车一模一样,我会换车吗?并不真地。我会做很多的工作来让它看起来像这样。
  • 有时需要封装的交换方法——显然在这种情况下不需要。使用数组返回多个值是此类问题的常见模式。
  • 不,你不能在 Java 中交换的原因是你有 no 指针。指针是在 c++ 中启用交换方法的原因。您可以交换两个对象字段的值,但不能使用通用交换功能。即便如此,它也只是按照上面汽车示例中所说的去做。
【解决方案3】:

Java 中的一切都是按值传递的,变量的值始终是基元或对对象的引用。

【讨论】:

    【解决方案4】:

    您需要通过引用传递参数,这在 java 中是不可能的。此外,整数是不可变的,因此您无法交换值,因为您没有 setValue 方法。

    【讨论】:

      【解决方案5】:

      正如 Svish 和其他人指出的那样,它是按值调用,而不是 Java 中的引用。由于您在 Java 中没有指针,因此您需要某种持有者对象才能以这种方式真正交换值。例如:

      static void swap(AtomicReference<Integer> a, AtomicReference<Integer> b) {
      
          Integer c = a.get();
          a.set(b.get());
          b.set(c);
      
      }
      
      public static void main(String[] args) {
      
          AtomicReference<Integer> a = new AtomicReference<Integer>(1);
          AtomicReference<Integer> b = new AtomicReference<Integer>(2);
      
          System.out.println("a = " + a);
          System.out.println("b = " + b);
      
          swap(a, b);
      
          System.out.println("a = " + a);
          System.out.println("b = " + b);
      
      }
      

      【讨论】:

      • P.S.使用 AtomicReference 可能对您没有多大意义,因为它是一种并发习语。如果您不需要线程安全行为,请编写您自己的持有者。
      • “你在 Java 中没有指针”。我猜Java有指针的概念,但它不是程序员可以使用的。
      • 据我所知,您在 Java 中有指针。它们只是被称为引用,你不能像在其他各种语言中那样在不同程度上操纵它们。
      • Java 中只有指针。如果您有引用(例如对那些指针),您可以修改这些指针包含的值
      【解决方案6】:

      如果你想为 Integer 对象实现一个交换方法,你必须将值包装到一个数组(或 ArrayList)中并在数组内交换。这是对您的代码的改编:

      public class Main {
      
          static void swap (Integer[] values) {
              if ((values == null) || (values.length != 2)) {
                throw new IllegalArgumentException("Requires an array with exact two values");
              }
      
              Integer t = values[0];
              values[0] = values[1];
              values[1] = t;
          }
      
          public static void main(String[] args) {
             Integer a = 1;
             Integer b = 2;
             Integer[] integers= new Integer[]{a,b};
             swap(integers);
             System.out.println("a=" + integers[0] + " b=" + integers[1]);
          } 
      }
      

      (刚刚添加了这个答案,因为 Svish 提到,“你不能真正在 Java 中创建交换方法” fg

      【讨论】:

        【解决方案7】:

        正如所有人都提到的那样,它是按价值传递的东西。

        只是想补充一点:您可以使用这种交换 GLOBAL 整数的方法。

        private void swap (){
             a ^= b;
             b ^= a;
             a ^= b;
        }
        

        它消除了另一个变量的使用,而且它更酷:)

        【讨论】:

        • 可能很酷,但可读性不是很好。
        • 很酷的交换版本 - 没有额外的变量,很棘手,很适合询问学生如何去做;-),但是......它在 Java 中不起作用:-(。或者是吗?
        • @WildWezyr 怎么不行?注意 a 和 b 在这里应该是全局的,否则你将需要使用上面提到的方法
        • a ^= b 与 a = a ^ b 相同。它影响将表达式(a ^ b)的值分配给局部变量a。其他两个赋值也只影响局部变量(在 swap 方法内),所以这个很酷的技巧不起作用。
        • @medopal: 如果我在执行你的方法 private void swap (Integer a, Integer b){...} 后打印变量 a&b )。提供语句 a ^= b 只是 a = a ^ b 的简写,所以它只是一个变量赋值,在 Java 中不能用于 swap 方法。
        【解决方案8】:

        使用 XOR 运算符是一个非常糟糕的主意:

        首先,它的可读性要差得多。其次,有时这更快,但现在情况正好相反。见

        Wikipedia

        供参考。

        【讨论】:

        • 仅供参考,因为 SO 会在他们获得支持/反对投票时重新调整答案,所以通常使用“添加评论”链接向您所指的答案添加评论而不是编写在新答案中发表评论。让您更容易弄清楚您在评论什么。
        【解决方案9】:

        Java 代码:

        class swap {
        
            int n1;
            int n2;
            int n3;
        
            void valueSwap() {
                n3 = n1;
                n1 = n2;
                n2 = n3;
            }
        
            public static void main(String[] arguments) {
        
                Swap trial = new Swap();
                trial.n1 = 2;
                trial.n2 = 3;
        
                System.out.println("trial.n1 = " + trial.n1);
                System.out.println("trial.n2 = " + trial.n2);
        
                trial.valueSwap();
        
                System.out.println("trial.n1 = " + trial.n1);
                System.out.println("trial.n2 = " + trial.n2);
        
            }
        }
        

        输出:

        trial.n1 = 2
        trial.n2 = 3
        trial.n1 = 3
        trial.n2 = 2
        

        【讨论】:

          【解决方案10】:

          使用扫描仪:

          import java.util.*;
          public class Swap {
           public static void main(String[] args){
            int i,temp,Num1,Num2;
            Scanner sc=new Scanner(System.in);
            System.out.println("Enter Number1 and Number2");
            Num1=sc.nextInt();
            Num2=sc.nextInt();
            System.out.println("Before Swapping Num1="+Num1+" Num2="+Num2);
            temp=Num1;
            Num1=Num2;
            Num2=temp;
            System.out.println("After Swapping Num1="+Num1+" Num2="+Num2);
           }    
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-28
            相关资源
            最近更新 更多