如何修改通过void方法传递的变量(必须为void)并更改方法外的值(Java)

时间:2015-04-11 00:48:00

标签: java variables methods arraylist void

我上高中并参加了AP计算机编程课程(Java)。在我的课程中,我必须创建一个void方法来对传入的数组进行排序。它必须是void(要求)并且需要修改传递给它的变量(要求)。我必须使用他们提供的跑步者代码。我对编码很新,但仍然对语言可以做什么和不能做什么感到困惑。排序有效,但我看不到如何修改main方法的传入变量。

public class InsertionSort extends Sort {
    public <T extends Comparable<T>> void sortList(ArrayList<T> arr) {
        ArrayList<T> arr2 = new ArrayList<T>(arr.size());

        for (int i = 0; i < arr.size(); i++) {
            boolean done = false;
            int insertIndex = 0;
            int k = i;
            T next = arr.get(i);

            while (k>0 && insertIndex == 0) {
                if (next.compareTo(arr2.get(k-1)) > 0) {
                    // System.out.println("if i" + i + " k" + k); 
                    insertIndex = k;
                    done = true;
                }

                k--;
            }

            arr2.add(insertIndex, arr.get(i));
        }
        //System.arraycopy(arr2,0,arr,0,arr2.size());
        arr = arr2; //<--my attempt to alter runner variable
        //System.out.println(" arr 2 = " + arr2);
        //System.out.println(" arr 1 = " + arr);
    }
}

// Runner

public static void main( String[] args )
{
  ArrayList<String> s = new ArrayList<String>();
  String[] sArr = { "you", "can", "observe", "a", "lot", "just", "by", "watching" };
  for ( String x : sArr ) { s.add( x ); }
  Sort ss = new InsertionSort();
  ss.sortList( s );
  System.out.println( s );
}

我基本上需要在调用ArrayList方法(已排序)时修改sortList()(s),然后从对System.out.println()的调用打印。

排序有效,但“s”不会改变,我不知道从哪里开始修复它。调用者完全一成不变(类要求),类和方法标题必须保持不变(出于同样的原因)。

我可能会在副本和粘贴中遗漏“{”或“}”。

6 个答案:

答案 0 :(得分:2)

您可以修改ArrayList arr的内容。首先,清空内容。然后添加第二个List中的元素。像

这样的东西
// arr = arr2; // <--my attempt to alter runner variable
arr.clear(); // <-- empty arr
arr.addAll(arr2); // <-- copy arr2 contents to arr.

List.clear()说(部分)

  

此调用返回后列表将为空。

List.addAll(Collection)说(部分)

  

将指定集合中的所有元素按指定集合的​​迭代器(可选操作)返回的顺序追加到此列表的末尾。

最后,您无法使用List修改调用方对arr = arr2;传入的引用,因为(即使Java始终按值传递),{的值也是{ {1}}是它的&#39; 参考

答案 1 :(得分:1)

您需要直接对arr列表进行排序,您无法将此类列表指定为java is pass by value。但是,您仍然可以实现此目的,因为传递的对象仍然可以访问引用:

public <T extends Comparable<T>> void sortList(ArrayList<T> arr) {

        ArrayList<T> arr2 = new ArrayList<T>(arr);

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

            boolean done = false;
            int insertIndex = 0;
            int k = i;
            T next = arr2.get(i);

            while (k > 0 && insertIndex == 0) {

                if (next.compareTo(arr2.get(k - 1)) > 0) {
                    insertIndex = k;
                    done = true;
                }

                k--;
            }
            arr.set(insertIndex, arr2.get(i));
        }
    }

我在算法中修改的内容:

  • arr2现在是arr的临时列表克隆。
  • 我们循环arr2并在arr2而不是arr上进行验证。
  • 我们设置arr
  • 的值,而不是添加

然后你的程序将输出

[a, can, observe, a, by, just, by, watching]

而不是

[you, can, observe, a, lot, just, by, watching]

答案 2 :(得分:1)

这与变量传递到方法的方式有关,Java有两种方法可以根据输入类型执行此操作。第一种是传递值,并在传递基元时使用。按值传递意味着将基本类型中保存的实际值复制到新的内存位置,然后该位置可供被调用方法使用。例如,int值0xDEADBEEF会将0xDEADBEEF的位模式复制到新位置,并将其传递给被调用的方法。

Java中的其他所有(非原始)都是一个对象(Object的实例),对象通过引用值传递。基本上所有持有对象的变量实际上都是引擎盖下的指针(它们是一个变量,它保存实际对象的基本内存位置,从堆中分配,而不是保持对象本身)。将对象值传递给方法时,不会复制对象,而是复制保存对象基址的变量。这意味着对该变量的任何操作都将引用(指向)调用方法所持有的原始对象。这也意味着如果重新分配“指向”对象的变量,则会丢失对该对象的引用,并且无法将其取回。

IE:

public static void doSomething(LinkedList<String> strings, int num) {
    if (strings == null)
        return;
    // here we modify the content of strings
    strings.add("NEW STRING!");
    // now the calling method can see the change, the list size
    // increased by 1 to anything that holds a reference to this list

    // here we lose our reference to strings
    strings = new LinkedList<String>();
    // we can no longer make changes to strings that the calling
    // method will see because we no longer have a reference to
    // the original list!

    // here we save, then change num
    int oldNum = num;
    num = Integer.MAX_VALUE;
    // the calling method has no way to know that num has changed.
    // it still thinks num = oldNum
}

希望这有助于澄清!

答案 3 :(得分:0)

而不是像在此处一样创建新数组

ArrayList<T> arr2 = new ArrayList<T>(arr.size());

在你的情况下只需编辑你得到的数组作为函数参数,你得到参数作为参数,这意味着你直接编辑对象

 public void sortList( ArrayList<T> arr ) 

我建议你在这里使用修饰符final,这样你就无法真正改变它所指向的对象。

 public void sortList(final ArrayList<T> arr ) 

答案 4 :(得分:0)

<{1>}在sortList内创建arr的副本:

ArrayList<T> arrCopy = new ArrayList<T>(arr);

清除arr后

arr.clear();

将代码arr替换为arrCopy

将代码arr2替换为arr

答案 5 :(得分:-1)

Java使用引用语义。因此,您可以将“arr”参数视为指向数组的指针。记住它只是一个指针,所以你可以逐个将arr2的内容复制到arr1,它应该可以正常工作。

代替:     arr = arr2

尝试:

for (int i=0; i<arr.size(); ++i) {
    arr[i] = arr2[i];
}