2012-04-15 5 views
6

が、これはC++のコードであるとしましょう:Javaの "ポインタ"の仕組みは?

void change(int& x){ 
    x++; 
} 

または

void change2(int* a){ 
    *a++; 
} 

どちらが正しい、グローバルXを変更するのでしょうか?

どうすればJavaのようなことをすることができますか?
具体的には、Vectorオブジェクトを指したいと思います。

しかし、Javaにはポインタがないので、私は何をすべきかわかりません。
インターネットを検索すると、Javaが何か他の方法でそれをしていると言う人がいましたが、実際の例は見つかりませんでした。

ありがとうございました 助けてください!

+0

Javaは常に値渡しです。 –

+0

答えは "あなたができない"可能性が高いです - しかし、私たちに関連するJavaコードを与えることから始める... –

+1

[Javaで参照渡す方法]の可能な複製(http://stackoverflow.com/questions/5614562) /どのようにJavaで参照渡し) –

答えて

12

Javaでは、ポインタの代わりにオブジェクトへの参照があります。参照によってプリミティブ型を渡すことはできませんが、オブジェクト内にプリミティブ型をラップし、そのオブジェクトへの参照を渡すことができます。

Javaではがラップされますが、intがありますが、このタイプは変更不可能なため、作成後に値を変更することはできません。 xに変更が呼び出し元に表示されます

void change(MutableInt x) { 
    x.increment(); 
} 

:あなたはしかし、ApacheのコモンズからMutableIntを使用することができます。


具体的には、私はあなたが変数vにベクトルへ参照を割り当てるVector v = ...;を書くときVectorオブジェクト

を指すようにしたいです。 Javaのリファレンスはポインタと非常によく似ています。参照は実際にはポインタを使って内部的に実装されています。

Javaは値渡しを使用します。ベクターをメソッドに渡すと、実際にはの参照がそのベクターにコピーされています。ベクターそのものをクローンしません。したがって、Javaで参照を渡すことは、C++でポインタを渡すことと非常によく似ています。

+0

私はこれについて気に入らないのは、Javaで非常に基本的なことをするためにサードパーティ製のlibが必要だという印象を与えるということです。私はOPが**本当にMutableIntやApache Commonsの何かを必要としないと確信しています。代わりに、彼はちょうど慣用的なJavaを学ぶ必要があります。確かに、彼のコードが実際に何をしたいのかがはっきりしないので、質問はよりよく答えるのが難しいだろう。 – Jonik

+0

私はこれが受け入れられた答えであることも好きではありません。 4つの方法の詳細については、http://stackoverflow.com/questions/5614562/how-to-do-the-equivalent-of-pass-by-reference-for-primitives-in-java/5614630#5614630を参照してください。サードパーティのライブラリをインポートすることなく、これを実行します。またはこれを行う一般的な方法については、dash1eの答えを参照してください。 – ToolmakerSteve

1

Javaは常に値渡しであり、C++のようにグローバル変数はありません。したがって、C++と同じようにしたい場合は、新しい値を返す必要があります。

Thusly:

public int change(int x) { 
    return ++x; 
    // or 
    // return x + 1; 
} 

それをテストするには:

int x = 2; 

change(x); 

System.out.println(x); // returns 2 

x = change(x); 

System.out.println(x); // returns 3 

だから、メソッドがchangeと呼ばれるようにする任意の意味がありません、それはcalculateThisIntの線に沿って、より賢明です。


Javaはオブジェクトを値渡しします。しかし、Mark ByersにはIntegerクラスが不変であることが記載されているため、Apache CommonsライブラリのMutableIntを使用できます。これはあなたがあなたの例のためにそれを自分で実装できる機能について説明するには:

public void change(MyInt i) { 
    i.increment(); 
} 

は使用法::

MyInt x = new MyInt(); 
x.setInt(2); 

change(x); 

System.out.println(x.getInt); // returns 3 

public class MyInt() { 

    public int i; 

    public void setInt(int i) { 
     this.i = i; 
    } 

    public int getInt() { 
     return this.i; 
    } 

    public int increment() { 
     this.i++; 
    } 

} 

あなたは、引数として上記MyIntオブジェクトを持っているあなたのchange機能を変更する必要があります


を変更したい場合オブジェクト...

public void changeVector(Vector v) { 
    // anything you do with 'v' will change it even 
    // for the scope that called this method 
} 

// Usage: 
Vector v = new Vector(); 
changeVector(v); 
// v should be changed after calling change vector method 

これはすべて意味があります。

+0

あなたはreturn ++ xを使う必要があります。 x ++を返す代わりに。 – Chris

+0

@Chris:修正されました。 – Spoike

+0

オブジェクトはJavaでは参照渡しされません。オブジェクトへの参照は値渡しされます。 –

4

Javaでは、参照によってintのようなプリミティブ型を渡すことはできません。それらは値だけで渡されます。

代わりにObjectsが参照渡しされているため、これを行うアーティファクトを見つけることができます。ここに2つの例があります。

この

int[] value = new int[1]; 
value[0] = 2; 

// call a method 
obj.setValue(value); 

// and in setValue 
public void setValue(int[] value) { 
    value[0] = 5; 
} 

または第二のアプローチのようなホルダークラスを使用して、単一の値の配列を使用します。この場合、

public class Holder<T> { 
    public T value; 
    public Holder(T value) { 
    this.value = value; 
    } 
} 

// then use it in this way 
Holder<Integer> h = new Holder<Integer>(2); 

obj.setValue(h); 

// and in setValue 
public void setValue(Holder<Integer> h) { 
    h.value = 5; 
} 

を私はホルダークラスはジェネリックで実装して使用しますが、あなたが持つことができます単純なホルダーでも、整数のためだけです。例:あなたが関数に渡されていたオブジェクトを置き換えることはできませんが

public class IntHolder { 
    public int value; 
    public IntHolder(int value) { 
    this.value = value; 
    } 
} 
+0

親愛なるSmRndGuy、これはあなたが探している答えです。 (PS:私はHolderクラスについて知りませんでしたので、大変ありがとうございます。) – guness

+0

@bluebrain注意してください、Java標準クラスではありません、自分でHolderを書く必要がありますが、それはとても簡単です。多分、時々、あなたはその問題を解決するための通常の方法であるので、別の図書館でホルダーを見つけることができます。 – dash1e

+0

その汎用的な 'Holder'クラスは、「ラッパー」を行う良い方法です。 – Spoike

0

は、あなたが直接フィールドを変更することやメソッドを呼び出すことにより、その状態を変更することができます。プリミティブへのポインタのようなものが必要な場合は、オブジェクトにラップします。

public class IntPointer { 
    public int value; 
    public IntPointer(int value) { 
     this.value = value; 
    } 
} 

その後、別の場所にあなたが言うことができる:

public static void change(IntPointer ipoint) { 
    ipoint.value++; 
} 
public static void main(String[] args) { 
    IntPointer a = new IntPointer(10); 
    change(a); 
} 

をこれは少し厄介に思えるかもしれないが、それはできるだけ頻繁にあなたと私のために来ていない、あなたのコードに従うために、あなたはこれを行うことができます思う。換言すれば、

public static void main(String[] args) { 
    ABPair ab = new ABPair(); 
    if (ACondition) { 
     ab.changeA(); 
    } 
} 

は、私のデータは、すでにオブジェクトのいくつかの並べ替えに包まれる傾向にある。だから、他の場所で

public class ABPair { 
    private int a = 0; 
    private int b = 0; 
    public static void changeA() { 
     a++; 
    } 
    public static void changeB() { 
     b++; 
    } 
} 

私が言うことができます。私はこのような何かをする可能性が高いと思います私はデータオブジェクトのメソッドを使用して変更を仲介する傾向があります。

0

どちらもグローバルxを変更しますか?

どうすればJavaのようなことをすることができますか?具体的には、私はVectorオブジェクト

に ポイントにしたい質問はやや曖昧ですが、私はあなたが最終的にあなたがものを保つことができるグローバルVectorをしたい印象を得ましたか。

これを行うには多くの方法がありますが、最も簡単な方法の1つは、アクセスするための静的な静的メソッドを使用して、という静的フィールドをクラス内に持つことです。 (または、直接アクセスされるだけでパブリック静的フィールドが、それは本当にJavaで慣用的ではありません。)

コードのどこにも
public class Foo { 
    private static List<Integer> globalVector = new Vector<Integer>(); 

    public static void add(int number){ 
     globalVector.add(number); 
    } 

    // ... plus whatever other accessors to the global list that you need 
} 

Foo.add(23); // modifies the global vector 

(ところで、Vectorはちょっと時代遅れでありますJavadocによれば、この例でも使用したListインターフェイスを実装するために改良されています)。

+0

**免責事項**:私はOPが望んでいたことを完全に誤解しているかもしれませんが、そうである場合はこれを削除します。 OPが実際に彼のコードで達成したいことが何であるかについて、質問は本当にはっきりしているはずです。 – Jonik

0

Javaは「参照」と呼ばれるものをサポートしています。参照は、C/C++のような言語でポインタのようにたくさん動作します。彼らはそれらの言語で "参照"と同じように動作しません。

CでのポインタとJavaでの参照の主な違いは以下のとおりです。

あなたは(つまり、あなたが「追加」することはできませんまたはJavaリファレンスから「引く」Javaでポインタ演算を行うことができません、参照を解除するか、別のものと比較することができます)。 互換性のない型にキャストすることはできません。Javaは型に強く、あなたは他のオブジェクトとしてメモリ内のバイトを「再解釈」できません。 ポインタのある種の用途では、実際の効果はありません(例えば、リンクリストは両方の言語で同じように動作します)。その違いは非常に大きくなります(Cの配列は、 。

Java参照は「制限付きポインタ」と呼ばれることがあります。