1

Java のオブジェクトへの参照が copy によって渡されることはわかっていますが、コピーは引き続き system の同じメモリを指しているため、別の function で複合オブジェクトの一部のデータを更新した後、元のデータを維持する必要があります。しかし興味深いことに、ここで何かがうまくいかない。私は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)は決して実行されず、これも決して実行されません 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です。そのため、この呼び出しでコピーによって渡される変数の参照はありませんでした。nullrootroot

解決策:

関数を変更します。

 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オブジェクトがあり、それらを混乱させています。デバッガーでオブジェクト ID (オブジェクト番号) を確認すると、それらが同じではないことがわかります。

于 2013-08-24T21:41:24.580 に答える
0

デバッガーで実行されるステートメントが表示されると言っていますが、どのオブジェクトroot.isEnd = true;が実行されているかについては言及していません。

メソッドinsertIntoTrie()再帰的に呼び出されるため、そのステートメントはおそらくオブジェクト自体ではなく、配列にあるTrieオブジェクトに対して実行されます。roottrie[]root

実際の実行は呼び出しに使用している引数に依存するprintAnagrams(String[] anagrams)ため、より具体的な回答が必要な場合は、それらを質問に追加してください。

更新:質問を編集した後、すべての"... Java のオブジェクトへの参照はコピーによって渡される"ことを知っていても、オブジェクト参照を誤用していることは明らかです 。あなたinsertIntoTrie()は故障しています。root引数がの場合、新しいオブジェクトを作成するつもりのようですが、引数が copy であるnullため、その新しいオブジェクトは失われます。メソッドの最後で、元のオブジェクト (クラス内のオブジェクト) のメンバー全体を出力すると、すべてのオブジェクトが.roottrie[]rootAnagramsTogethernull

于 2013-08-24T21:53:43.217 に答える