1

私はJava に関するこの優れた記事reference semanticsを読んでいたJon Skeetところ、彼は次のように述べています。

仮パラメータ s を取る f という名前の手続きが存在すると仮定します。実パラメータ g を指定してその関数を呼び出します。

呼び出しコード:

         f( g )

関数:

   procedure f( s )
   begin
     -- body of the procedure
   end;

Java のすべてのオブジェクト インスタンスはヒープに割り当てられ、オブジェクト参照を介してのみアクセスできます。したがって、次のものがあれば:

       StringBuffer g = new StringBuffer( "Hello" );

変数 g には文字列 "Hello" が含まれていません。文字列 "Hello" を含むオブジェクト インスタンスへの参照 (またはポインター) が含まれています。

したがって、次に f( g ) を呼び出すと、f はその仮パラメーター s を自由に変更して、別の StringBuffer を指すようにしたり、null に設定したりできます。関数 f は、たとえば " World" を追加して StringBuffer を変更することもできます。これによりその StringBuffer の値が変更されますが、その StringBuffer の値は実際のパラメーター g の値ではありません。

私の理解は間違っているかもしれません。以下のプログラムは、メソッドに渡される Stringbuffer を変更します

public class MutabilityStringBuffer {
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer("hello");
        System.out.println("String before append: "+ sb.toString());
        addString(sb);
        System.out.println("Sting after append "+ sb.toString());

        String s = "hello";
        System.out.println("String before append: "+ s);
        addString(s);
        System.out.println("Sting after append "+ s);

    }
    public static void addString(StringBuffer word){
        word.append(" world!");
    }
    public static void addString(String word){
        word+=" world!";
    }

}

もちろん、Jon Skeet が間違っているわけではありません。Stringbufferしかし、メソッドに渡すことで変更できることがわかりますstringbuffer。これは変更可能であるため、Skeet が投稿したものとは少し矛盾しています。ここで私の理解を明確にしてください。

ありがとう

4

2 に答える 2

1

これは死ぬほど議論されました。とにかく、アイドル時間が与えられたので、これが私の応答です。これは私がいつも提供するのと同じ回答であり、私がいつもリンクしている評価戦略に関する同じウィキペディアの記事にリンクしています。


(オブジェクト) 共有による呼び出しという用語を使用すると、Java (および Python、C# などを含む他の多くの言語) でオブジェクトを引数として渡すセマンティック動作を説明するときに、ほとんどのあいまいさが取り除かれることがわかります。そうすることで、[im]mutability に関する考慮事項が明確に識別されます。つまり、メソッド内でアクセスされるオブジェクトは、外部と同じオブジェクトです! この呼び出し/評価戦略中に、新しいオブジェクトが作成、コピー、複製、または複製されることはありません。そのため、オブジェクトに加えられた変更可能な変更は、同じ「共有」オブジェクトに影響します。

Call by Valueを使用してオブジェクトの参照を渡すことは実装の詳細ですが、Java 言語仕様 (JLS)で詳しく説明されています。Javaの場合、オブジェクトへの参照の値による呼び出しと言う方がより「正確」ですが、これは値による呼び出しとしてまだ実装されています。(ただし、 ECMAScriptなどの一部の言語は、そのような実装の詳細について説明することなく、セマンティクスを共有することでまったく同じ Call を実現します。)

混乱を避けるために、参照による呼び出しのみを使用して、呼び出された関数がパラメーターへの再割り当てを通じて呼び出し元の変数バインディング(オブジェクトの可変性とは直交する) を変更できることを意味します。残念ながら、一部の言語サークルでは、Call by Referenceに代替の (そして紛らわしい) 意味が与えられています。

于 2013-09-12T21:19:00.687 に答える