Javaで「参照による呼び出し」を行う方法は?(1960年代から査読されたCSの文献で使用されているのと同じ方法でその用語を使用していると仮定します。簡単な説明については、このWikipediaページを参照してください。)
Javaはポインタをサポートしていないので、CやC ++のように、Javaで参照によって関数を呼び出すにはどうすればよいでしょうか。
12 に答える
Javaでは、実際の参照渡しは不可能です。Javaは、参照を含め、すべてを値で渡します。ただし、コンテナオブジェクトを使用してシミュレートできます。
これらのいずれかをメソッドパラメータとして使用します。
- 配列
- コレクション
- AtomicXYZクラス
また、メソッドでその内容を変更すると、変更された内容が呼び出し元のコンテキストで使用できるようになります。
おっと、あなたはどうやら参照によってメソッドを呼び出すことを意味します。メソッドはJavaの第1レベルの市民ではないため、これはJavaでも不可能です。これはJDK8で変更される可能性がありますが、当面は、この制限を回避するためにインターフェースを使用する必要があります。
public interface Foo{
void doSomeThing();
}
public class SomeFoo implements Foo{
public void doSomeThing(){
System.out.println("foo");
}
}
public class OtherFoo implements Foo{
public void doSomeThing(){
System.out.println("bar");
}
}
コードで使用すると、で簡単に置き換えることがFoo
できます。SomeFoo
OtherFoo
Javaで参照による呼び出しを行う方法は?
Javaでは参照による呼び出しはできません。限目。何も近づいていません。また、値による参照の受け渡しは、参照による呼び出しと同じではありません。
(実際の「参照による呼び出し」では、次のようなことができます。
void swap(ref int i, ref int j) { int tmp = *i; *i = *j; *j = tmp }
int a = 1;
int b = 2;
swap(a, b);
print("a is %s, b is %s\n", a, b); // -> "a = 2, b = 1"
Javaではそれを行うことはできません。)
Javaはポインタをサポートしていないので...
これは技術的には真実ですが、あなたがやろうとしていることを妨げるものではありません。
Javaは参照をサポートします。これは、最も重要な点でポインターのようなものです。違いは、参照を算術演算したり、整数型との間で変換したりすることによって、参照をメモリアドレスとして扱うことができないことです。また、概念がJavaまたはJVMアーキテクチャに存在しないため、変数への参照を作成することはできません。
CやC++のように、Javaで参照によって関数を呼び出すことはどのように可能ですか?
重要な注意:これは「参照による呼び出し」ではありません。関数1への参照を使用した「値による呼び出し」です。
Java 8より前は、関数への参照は値としてサポートされていませんでした。したがって、それらを引数として渡すことはできず、変数に割り当てることもできません。
ただし、1つのインスタンスメソッドでクラスを定義し、関数参照の代わりにクラスのインスタンスを使用することができます。他の回答は、このアプローチの例を示しています。
Java 8以降では、メソッド参照は::
構文を使用してサポートされます。メソッドリファレンスには次の4種類があります。
- 静的メソッドへの参照:
ContainingClass::staticMethodName
- 特定のオブジェクトのインスタンスメソッドへの参照:
containingObject::instanceMethodName
- 特定のタイプの任意のオブジェクトのインスタンスメソッドへの参照:
ContainingType::methodName
- コンストラクターへの参照:
ClassName::new
1-教育学的観点から、CとC ++が&
参照による呼び出しと関数ポインターの両方にこの記号を使用しているのは、残念なことです。しかし、言語デザインの観点から、私はそのデザインの選択に同意しません。
通常、Javaでは、これはインターフェイスを使用して解決されます。
Collections.sort(list, new Comparator() {
@Override
public int compareTo(Object o1, Object o2) {
/// code
}
});
package jgf;
public class TestJavaParams {
public static void main(String[] args) {
int[] counter1 = new int[1];
counter1[0] = 0;
System.out.println(counter1[0]);
doAdd1(counter1);
System.out.println(counter1[0]);
int counter2 = 0;
System.out.println(counter2);
doAdd2(counter2);
System.out.println(counter2);
}
public static void doAdd1(int[] counter1) {
counter1[0] += 1;
}
public static void doAdd2(int counter2) {
counter2 += 1;
}
}
出力は次のようになります。
0
1
0
0
最良の方法は、アクションを実行するインターフェースを使用することです。
// Pass a Runnable which calls the task() method
executor.submit(new Runnable() {
public void run() {
task();
}
});
public void task() { }
リフレクションを使用して任意のメソッドを呼び出すことができます
Method method = MyClass.class.getMethod("methodToCall", ParameterType.class);
result = method.invoke(object, args);
Javaでは、プリミティブを除いて、オブジェクトをメソッド/関数に渡すのは常に参照によるものです。例については、 OliCharlesworthの回答を参照してください。
プリミティブ型の場合、配列を使用してラップできます。例:
public void foo(int[] in){
in[0] = 2;
}
int[] byRef = new int[1];
byRef[0] = 1;
foo(byRef);
// ==> byRef[0] == 2.
Javaでは、値による呼び出しのみが許可されます。ただし、オブジェクトへの参照は、値による呼び出しを使用して、呼び出された関数に転送できます。これらの参照を使用して、呼び出された関数でオブジェクトのデータを操作すると、この変更は呼び出し元の関数にも表示されます。ポインターの場合のように参照に対してポインター演算を行うことはできませんが、参照は、C /C++で「*」演算子として機能するピリオド演算子を使用してオブジェクトのデータを指すことができます。
JAVAは、オブジェクトを使用した内部参照を許可します。この割り当てを書くと、Obj o1 = new Obj(); Obj o2 = o1; o1とo2の両方が同じアドレスを指しているということは何をしますか。オブジェクトのスペースを操作すると、他のオブジェクトのスペースにも反映されます。
したがって、これを行うには、上記のように、配列、コレクションのいずれかを使用できます
http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html
Javaは参照によってオブジェクトを操作し、すべてのオブジェクト変数は参照です。ただし、Javaは参照によってメソッド引数を渡しません。それらを値で渡します。
JavaからHerbertShildtによる完全なリファレンス第9版:「オブジェクトをメソッドに渡すと、オブジェクトは事実上参照による呼び出しによって渡されるため、状況は劇的に変化します。クラスタイプの場合、オブジェクトへの参照のみを作成します。したがって、この参照をメソッドに渡すと、それを受け取るパラメータは、引数によって参照されるものと同じオブジェクトを参照します。これは、オブジェクトが次のように機能することを意味します。参照による呼び出しを使用してメソッドに渡される場合。メソッド内のオブジェクトへの変更は、引数として使用されるオブジェクトに影響します。」
package objectpassing;
public class PassObjectTest {
public static void main(String[] args) {
Obj1 o1 = new Obj1(9);
System.out.println(o1.getA());
o1.setA(3);
System.out.println(o1.getA());
System.out.println(sendObj1(o1).getA());
System.out.println(o1.getA());
}
public static Obj1 sendObj1(Obj1 o)
{
o.setA(2);
return o;
}
}
class Obj1
{
private int a;
Obj1(int num)
{
a=num;
}
void setA(int setnum)
{
a=setnum;
}
int getA()
{
return a;
}
}
OP:9 3 2 2
getA()の最後の呼び出しは、元のオブジェクトフィールド'a'がメソッドpublicstatic Obj1 sendObj1(Obj1 o)の呼び出しで変更されたことを示しています。
Javaでは参照による呼び出しはできません。限目。何も近づいていません。また、値による参照の受け渡しは、参照による呼び出しと同じではありません。
私はこれを行うために配列を使用しました...
package method;
import java.util.Scanner;
public class InterChange {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int a[]=new int[2];
System.out.println("Enter two values");
for(int i=0;i<2;i++) {
a[i]=sc.nextInt();
}
hange(a);
for(int i=0;i<2;i++) {
System.out.println(a[i]);
}
}
static int hange(int b[])
{
int temp;
temp=b[0];
b[0]=b[1];
b[1]=temp;
return b[0]&b[1];
}
}
はい、「参照渡し」によって別の方法で参照による呼び出しを実装できます。
- 作成したクラスの参照オブジェクトを渡す必要があります。
- 次に、元のデータに反映されるメンバー関数(。)によってオブジェクトのデータを操作できます。
以下のコードでは、元のデータ->xは参照オブジェクトを渡すことによって操作されます。
public class Method_Call {
static int x=50;
public void change(Method_Call obj) {
obj.x = 100;
}
public static void main(String[] args) {
Method_Call obj = new Method_Call();
System.out.println(x);
obj.change(obj);
System.out.println(x);
}
}
出力:50100