2013-08-24 65 views
1

我知道對java中對象的引用是通過複製傳遞的,但副本仍然指向系統中的同一內存,所以在更新另一個函數中的複雜對象的某些數據之後,應該維護原始數據。但有趣的是,這裏出了問題。我正在與Tries合作。丟失數據的複雜對象

這裏是我的執行線索的,這是因爲一些自定義的規則相當定製的實現:

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)從不執行,所以是這是從來沒有執行anagramUtil(root.trie[i], anagrams);。該程序只是繼續執行continue聲明。 不應該是這種情況,因爲我已經看到root.trie[i]正在接收值。爲什麼會發生這種情況?我對java很陌生。

+0

[This](http://stackoverflow.com/a/40523/645270)可以幫助 – keyser

+0

調用'printAnagrams(String [] anagrams)'時使用了哪些參數? –

+0

用參數編輯我的代碼。 –

回答

0

你的程序中有很多Trie對象,你很困惑它們。如果使用調試器檢查對象標識(對象編號),則會看到它們不相同。

+0

是的,我確實看到了id不一樣。爲什麼會發生? –

0

你說的是你在調試器中看到要執行的語句root.isEnd = true;,但是你沒有提到哪個對象正在執行。

insertIntoTrie()方法被稱爲遞歸這樣,這種說法可能是對Trie對象的root在其trie[]數組,但不能爲root對象本身執行。

由於實際執行取決於您用來呼叫printAnagrams(String[] anagrams)的參數,如果您需要更具體的答案,請將這些參數添加到您的問題中。

更新:好您編輯您的問題後,很明顯,你可以將這個錯誤被濫用的對象引用,即使你知道,所有「......在Java對象的引用是通過複製傳遞」 。您的insertIntoTrie()有問題。看起來你打算創建一個新對象,如果參數rootnull但是新對象將會丟失,因爲root參數是副本。如果您打印原始root對象(AnagramsTogether類中的對象)的整個trie[]成員,則在方法結束時,您會看到所有對象都是null

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(...)函數之前的對象。