1

我知道java中对对象的引用是通过copy来传递的,但是copy仍然指向系统中的同一个内存,所以在另一个函数中更新了复杂对象的一些数据之后,我应该维护原始数据。但有趣的是,这里出了点问题。我正在与 Tries 合作。

这是我对 Trie 的实现,由于一些自定义规则,它是相当自定义的实现:

public class Trie {
    boolean isEnd;
    Trie trie[] = new Trie[256];
    ArrayList<Integer> indexNode;

    public static Trie createTrieNode() {
        Trie temp = new Trie();
        temp.isEnd = false;
        temp.indexNode = new ArrayList<Integer>();
        for (int i = 0; i < temp.trie.length; i++) {
            temp.trie[i] = null;
        }

        return temp;
    }

    public static void insertIntoTrie(Trie root, char[] alpha, int index, int i) {
        if (root == null)
            root = createTrieNode();
        if (i < alpha.length)
            insertIntoTrie(root.trie[alpha[i] - 'a'], alpha, index, i + 1);
        else {
            if (root.isEnd == true) {
                root.indexNode.add(index);
            } else {
                root.isEnd = true;
                root.indexNode.add(index);
            }
        }

    }

}

现在我的对象root来自这个类,在调试器中我可以看到这个语句正在执行:root.isEnd = true;

班级:

 public class AnagramsTogether {
        public Trie root = new Trie();
        public void printAnagrams(String[] anagrams){
            char[] buffer;
            for (int i = 0; i < anagrams.length; i++) {
                buffer = anagrams[i].toCharArray();
                Arrays.sort(buffer);
              Trie.insertIntoTrie(root, buffer, i, 0);
            }
            AnagramsUtil.anagramUtil(root,anagrams);
        }
  }

但是什么时候root经过这里AnagramsUtil.anagramUtil(root,anagrams);

public class AnagramsUtil {

    public static void anagramUtil(Trie root, String[] anagrams) {

        if (root.isEnd == true) {

            for (Iterator<Integer> iterator = root.indexNode.iterator(); iterator
                    .hasNext();) {
                Integer integer = (Integer) iterator.next();
                System.out.println(anagrams[integer]);
            }
        } else {
            for (int i = 0; i < root.trie.length; i++) {
                if (root.trie[i] == null)
                    continue;
                anagramUtil(root.trie[i], anagrams);
            }
        }
    }

}
public class Anagram{
                   public static String string[] = {"cat", "dog", "god","act", "tac","gdo"};
                   public static void main(String args){
                      new AnagramsTogether().printAnagrams(Anagram.string); 
                 }
}

此语句if (root.isEnd == true)从未执行过,因此 this 从未执行过 anagramUtil(root.trie[i], anagrams);。该程序只是继续执行该continue语句。这不应该是这种情况,因为我已经看到root.trie[i] 接收值。为什么会发生这种情况?我对 java 还很陌生。

4

3 回答 3

0

在Java中,null不是对象,它只是一种特殊类型。所以null没有参考。因此,例如:

Trie root = null;
insertIntoTrie(root, alpha, index, i); 
// after called this function, root = null

调用这个函数之后,root仍然是null因为在调用这个函数之前变量root还不是一个对象。因此,root在此调用中没有要通过副本传递的变量的任何引用。

解决方案

改变你的功能:

 public static void insertIntoTrie(Trie root, char[] alpha, int index, int i) {
    if (root == null)
        root = createTrieNode();
    if (i < alpha.length)
        insertIntoTrie(root.trie[alpha[i] - 'a'], alpha, index, i + 1);
    else {
        if (root.isEnd == true) {
            root.indexNode.add(index);
        } else {
            root.isEnd = true;
            root.indexNode.add(index);
        }
    }

}

进入 :

public static void insertIntoTrie(Trie root, char[] alpha, int index, int i) {
    if (i < alpha.length) {
        if (root.trie[alpha[i] - 'a'] == null) {
            root.trie[alpha[i] - 'a'] = createTrieNode();
        }
        insertIntoTrie(root.trie[alpha[i] - 'a'], alpha, index, i + 1);
    }
    else {
        if (root.isEnd == true) {
            root.indexNode.add(index);
        } else {
            root.isEnd = true;
            root.indexNode.add(index);
        }
    }

}

此解决方案确保root在传递给函数之前始终是一个对象insertIntoTrie(...)

于 2013-08-26T21:08:49.383 回答
0

你的程序中有很多Trie对象,你把它们弄糊涂了。如果您使用调试器检查对象标识(对象编号),您会发现它们并不相同。

于 2013-08-24T21:41:24.580 回答
0

您是说您在调试器中看到root.isEnd = true;要执行的语句,但是您没有提及正在执行哪个对象

您的insertIntoTrie()方法是递归调用的,因此该语句可能是针对其数组中的Trie对象执行的,而不是针对对象本身。roottrie[]root

由于实际执行取决于您用来调用的参数,printAnagrams(String[] anagrams)如果您需要更具体的答案,请将这些参数添加到您的问题中。

更新:好的,在您编辑完您的问题后,很明显您犯了滥用对象引用的错误,即使您知道所有 “...对 java 中对象的引用都是通过副本传递的”。你insertIntoTrie()的有问题。root如果参数是,您似乎打算创建一个新对象,null但是新对象将丢失,因为root参数是一个副本。在方法结束时,如果您打印原始对象的整个trie[]成员(类中的那个),您将看到所有对象都是.rootAnagramsTogethernull

于 2013-08-24T21:53:43.217 回答