1

Java は「値渡し」言語です。つまり、変数をメソッドに送信し、その変数が新しいオブジェクトを指すようにしても、外部変数には影響しません。

public void one() {

String s = "one";
two(s);
System.out.println(s);

}

public void two( String s ) {
s = "two";
}

「一」と書きます。

これを防ぐ方法はありますか?sまたは、メソッド内で実際に「2」に変更する最も一般的なソリューションまたはパターンは何ですか?

4

11 に答える 11

2

それを防ぐことはできません。

次のような一般的なラッパーでエミュレートできます。

class _<T>{
    public T _;
    public _(T t ) {
        _ = t;
    }
    public String toString(){ return _.toString(); }
}

そして、あなたが意図したようにそれを使用してください。

class GeneriWrapperDemo {
    public static void main(String [] args ) {
        _<String> one = new _<String>("One");
        two( one );
        System.out.println( one );
    }
    public static void two( _<String> s ) {
        s._ = "two";
    }
}

でも見た目が悪い。参照自体を変更するのが最善だと思います:

public String two( String a ) {
     return "two";
}

そしてそれを使う

 String one = "one";
 one = two( one );

:)

于 2010-07-01T16:06:43.343 に答える
1

参照渡しはできません-少なくとも変数自体はできません。すべてのパラメーターは値によって渡されます。ただし、オブジェクトには参照が含まれており、それ自体が参照として表されます。オブジェクトの内部はいつでも変更でき、変更を反映させることができます。したがって、配列を送信するか、ラッパークラスを作成するか、独自の参照オブジェクトを作成します。

class Ref<T> {
  T obj;
  public Ref(T value) {
    this.obj = value;
  }
  public void set(T value) {
    obj = value;
  }
  public T get() {
    return obj;
  }
}

他の人が言っているように、Stringとにかく変更可能ではないので、ここで実際に文字列を変更するのではなく、変数ポイントを逆にするので、単に新しい文字列を返さないことはあまり意味がありません。

于 2010-07-01T15:49:13.697 に答える
1

文字列を含むオブジェクトを作成し、それをメソッドに渡します。

public class StringHolder {
    public String s;

    public StringHolder(String s) {
        this.s = s;
    }
}

その場合、コードは次のようになります。

public void two(StringHolder sh) {
    sh.s = "two";
}

StringHolder sh = new StringHolder("one");
two(sh);
System.out.println(sh.s);

ただし、上記の例では、必要な値を返すことができます。

public String two(String s) {
    return "two";
}

String s = "one";
s = two(s);
System.out.println(s);

また、StringsについてはStringBuffer、いつでも使用できます。これは変更可能です。

public void two(StringBuffer buf) {
    buf.setLength(0);
    buf.append("two");
}
于 2010-07-01T15:43:06.437 に答える
1

可変オブジェクトの場合sは、その値(つまり、データメンバーの値)を変更できます。そして、メンバーもなることができStringます。Stringこれは不変であるため、パラメーターを直接操作することはできません。したがって、パラメーターを「変更」する唯一の方法は、参照を別のオブジェクトに向けることです。

于 2010-07-01T15:43:41.367 に答える
1

Java が値渡しするのを防ぐことはできません。それが言語のセマンティクスです。

やりたいことに応じて、何らかの方法でそれを回避できます。

return渡されたパラメーターに基づいて新しい値を作成できます。

static String scramble(String s) {
    return s.replaceAll("(.*) (.*)", "$2, $1");
}

// then later...
String s = "james bond";
s = scramble(s);
System.out.println(s); // prints "bond, james"

変更可能なものを渡すこともできます:

static void scramble(StringBuilder sb) {
    int p = sb.indexOf(" ");
    sb.append(", ").append(sb.substring(0, p)).delete(0, p+1);
}

// then later...
StringBuilder sb = new StringBuilder("james bond");
scramble(sb);
System.out.println(sb); // prints "bond, james"
于 2010-07-01T15:52:54.873 に答える
0

オブジェクトを含むラッパーを作成し、ラッパーの内容を変更します。

public class StringWrapper {
    private String str;    
    public String getString() {
       return str;
    }
    public String setString(String str){
        this.str = str;
    }
    public String toString() {
        return str;
    }
}

public void one() {
    StringWrapper s = new StringWrapper();
    s.setString("one");
    two(w);
    // This will print "two"
    System.out.println(s);
}
public void two( StringWrapper  s ) {
    s.setString("two");
}
于 2010-07-01T15:52:33.963 に答える
0

文字列は不変です...ただし、それ以外の場合は、メソッドを呼び出して同じオブジェクトを操作し、それによって文字列値を変更するだけです。

あなたに代わって仕事をするJavaクラスはたくさんあると思いますが、パブリックフィールドまたはsetter/getterのいずれかを使用してカプセル化クラスを作成するだけで独自のクラスを作成することもできます。前者の例は次のようなものです。

public class EncapsulatedString
{
    public String str;

    public EncapsulatedString(String s)
    {
        str = s;
    }
}
于 2010-07-01T15:44:26.333 に答える
0

長さ 1 の配列は少し醜いですが、完全に機能するソリューションです。余分なラッパー クラスを作成する必要はありません。

public void one() {
    String[] s = new String[]{"one"};
    two(s);
    System.out.println(s[0]);
}

public void two(String[] s) {
    s[0] = "two";
}

このパターンは、参照渡しが広く適用されている古い (C などの) コードを変換する場合に特に役立ちます。

とはいえ、新しい新鮮な値を返すことは、「入力」値を変更することよりも常に混乱を招きません。

于 2010-07-01T15:48:37.420 に答える
0

私の頭に浮かぶ醜い解決策の 1 つは、長さ 1 の String 配列を渡すことです。これは私が推奨するものではありませんが、やりたいと感じたら...

  1  public class One {
  2 
  3     public static void main( String[] _ ) {
  4         String[] s = {"one"};
  5         two(s);
  6         System.out.println(s[0]);
  7     }
  8 
  9     public static void two( String[] s ) {
 10         s[0] = "two";
 11     }
 12 }
于 2010-07-01T15:56:22.513 に答える
0

変更可能な StringBuffer または StringBuilder を使用します。

于 2010-07-01T16:21:49.677 に答える
-1

Java は値渡し言語ではありません。それどころか、それは参照渡し言語です。(参照渡しとは、元の「ポインター」を C++ で許可されているように他の場所を指すように変更できるという意味ではありません)。値によって渡される唯一のものはプリミティブ ( int、など)longです。 オブジェクト参照は常に参照によって渡されます。そのため、オブジェクトがその内容の変更をサポートできる場合 (たとえば、getter および setter メソッドを介して)、変更することができます。 char

String具体的には不変です。つまり、その内容は決して変更されない可能性があります。したがって、特定の質問について、ローカル変数「s」によって参照される文字列を変更する場合は、オブジェクトの新しいインスタンスへの参照を提供する必要がありStringます。

例:

public void one()  
{
    String s = "one";
    s = two(); // Here your local variable will point to a new instance of a String with the value "two"
    System.out.println(s);
}

public String two() 
{
  return "two";
}

-以外のオブジェクトを使用する場合はString、それらの内容を更新する setter メソッドを定義できます。

于 2010-07-01T15:56:17.683 に答える