私はJavaにポインターがないことを知っていますが、Javaプログラムはポインターを使用して作成でき、これはJavaの専門家である数人が行うことができると聞きました。本当ですか?
私はJavaにポインターがないことを知っていますが、Javaプログラムはポインターを使用して作成でき、これはJavaの専門家である数人が行うことができると聞きました。本当ですか?
回答:
Javaのすべてのオブジェクトは参照であり、ポインターのように使用できます。
abstract class Animal
{...
}
class Lion extends Animal
{...
}
class Tiger extends Animal
{
public Tiger() {...}
public void growl(){...}
}
Tiger first = null;
Tiger second = new Tiger();
Tiger third;
nullの逆参照:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
エイリアシングの問題:
third = new Tiger();
first = third;
失われた細胞:
second = third; // Possible ERROR. The old value of second is lost.
これを安全にするには、最初に秒の古い値が必要ないことを確認するか、別のポインタに秒の値を割り当てる必要があります。
first = second;
second = third; //OK
他の方法(NULL、new ...)で2番目の値を指定すると、同様に潜在的なエラーが発生し、それが指すオブジェクトが失われる可能性があることに注意してください。
Javaシステムは、OutOfMemoryError
newを呼び出したときに例外()をスローし、アロケータが要求されたセルを割り当てることができません。これは非常にまれであり、通常、暴走した再帰が原因です。
言語の観点からは、オブジェクトをガベージコレクターに放棄してもエラーにはなりません。これは、プログラマが知っておく必要があることです。同じ変数が異なる時点で異なるオブジェクトを指す可能性があり、ポインターがそれらを参照していない場合、古い値が再利用されます。ただし、プログラムのロジックでオブジェクトへの参照を少なくとも1つ維持する必要がある場合は、エラーが発生します。
初心者はしばしば次のエラーを犯します。
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
あなたが言うつもりだったのは:
Tiger tony = null;
tony = third; // OK.
不適切なキャスティング:
Lion leo = new Lion();
Tiger tony = (Tiger)leo; // Always illegal and caught by compiler.
Animal whatever = new Lion(); // Legal.
Tiger tony = (Tiger)whatever; // Illegal, just as in previous example.
Lion leo = (Lion)whatever; // Legal, object whatever really is a Lion.
Cのポインター:
void main() {
int* x; // Allocate the pointers x and y
int* y; // (but not the pointees)
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
*y = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
*y = 13; // Dereference y to store 13 in its (shared) pointee
}
Javaのポインター:
class IntObj {
public int value;
}
public class Binky() {
public static void main(String[] args) {
IntObj x; // Allocate the pointers x and y
IntObj y; // (but not the IntObj pointees)
x = new IntObj(); // Allocate an IntObj pointee
// and set x to point to it
x.value = 42; // Dereference x to store 42 in its pointee
y.value = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
y.value = 13; // Deference y to store 13 in its (shared) pointee
}
}
更新:コメントで提案されているように、Cにはポインタ演算があることに注意する必要があります。ただし、Javaにはありません。
Javaにはポインタがあります。Javaでオブジェクトを作成するときはいつでも、実際にはオブジェクトへのポインターを作成しています。このポインタは別のオブジェクトまたはに設定できnull
、元のオブジェクトは引き続き存在します(ガベージコレクションは保留中)。
Javaで実行できないことは、ポインタ演算です。特定のメモリアドレスを逆参照したり、ポインタをインクリメントすることはできません。
本当に低レベルにしたい場合、それを行う唯一の方法はJava Native Interfaceを使用することです。それでも、低レベルの部分はCまたはC ++で実行する必要があります。
Javaにはポインターのデータ型がないため、Javaでポインターを使用することはできません。少数のエキスパートでさえ、Javaでポインターを使用できません。
「Java言語環境」の最後のポイントも参照してください。
Javaにはポインターがありますが、C ++またはCのように操作することはできません。オブジェクトを渡すときは、そのオブジェクトへのポインターを渡しますが、C ++と同じ意味ではありません。そのオブジェクトは逆参照できません。ネイティブアクセサーを使用して値を設定すると、Javaがポインターを介してメモリの場所を認識しているため、値が変化します。しかし、ポインタは不変です。ポインタを新しい場所に設定しようとすると、代わりに、他のオブジェクトと同じ名前の新しいローカルオブジェクトが作成されます。元のオブジェクトは変更されていません。ここに違いを示す簡単なプログラムがあります。
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
public static void main(String[] args) throws java.lang.Exception {
System.out.println("Expected # = 0 1 2 2 1");
Cat c = new Cat();
c.setClaws(0);
System.out.println("Initial value is " + c.getClaws());
// prints 0 obviously
clawsAreOne(c);
System.out.println("Accessor changes value to " + c.getClaws());
// prints 1 because the value 'referenced' by the 'pointer' is changed using an accessor.
makeNewCat(c);
System.out.println("Final value is " + c.getClaws());
// prints 1 because the pointer is not changed to 'kitten'; that would be a reference pass.
}
public static void clawsAreOne(Cat kitty) {
kitty.setClaws(1);
}
public static void makeNewCat(Cat kitty) {
Cat kitten = new Cat();
kitten.setClaws(2);
kitty = kitten;
System.out.println("Value in makeNewCat scope of kitten " + kitten.getClaws());
//Prints 2. the value pointed to by 'kitten' is 2
System.out.println("Value in makeNewcat scope of kitty " + kitty.getClaws());
//Prints 2. The local copy is being used within the scope of this method.
}
}
class Cat {
private int claws;
public void setClaws(int i) {
claws = i;
}
public int getClaws() {
return claws;
}
}
これはIdeone.comで実行できます。
JavaにはCのようなポインターはありませんが、変数によって「参照される」ヒープ上に新しいオブジェクトを作成できます。ポインタの欠如は、Javaプログラムがメモリの場所を不正に参照するのを阻止することであり、ガベージコレクションをJava仮想マシンが自動的に実行できるようにします。
Unsafeクラスを使用してアドレスとポインタを使用できます。ただし、その名前が示すように、これらの方法は安全ではなく、一般に悪い考えです。誤った使用法は、JVMをランダムに停止させる可能性があります(実際には、C / C ++でポインターを誤って使用すると、同じ問題が発生します)
ポインターに慣れていて、他の方法でコーディングする方法がわからないので、ポインターが必要だと思うかもしれませんが、そうではないことがわかり、その方がよいでしょう。
技術的には、すべてのJavaオブジェクトはポインタです。ただし、すべてのプリミティブ型は値です。これらのポインタを手動で制御する方法はありません。Javaは内部的に参照渡しを使用しています。
いいえ、違います。
Javaにはポインターがありません。あなたがいる場合、本当に欲しかったあなたは反射のようなものを周りに構築することにより、それらをエミュレートしようとすることができますが、それはすべてのだろう複雑のどれとポインタのメリットを。
Javaにはポインターが必要ないため、ポインターはありません。この質問からどのような答えを期待していましたか。つまり、何かを深めるためにそれらを使用できることを望んでいましたか、それとも単なる好奇心でしたか?
プリミティブを除き、Javaのすべてのオブジェクトは参照コピーによって関数に渡されます。
つまり、これは、オブジェクト自体のコピーではなく、元のオブジェクトへのポインタのコピーを送信することを意味します。
これを理解するための例が必要な場合は、コメントを残してください。
swap
2つのオブジェクトを交換する関数をJavaで作成することはできません。
Godfrey Nolanによる「Decompiling Android」という本から
セキュリティでは、Javaでポインターが使用されていないため、ハッカーがアプリケーションからオペレーティングシステムに侵入することはできません。ポインターがないということは、他の何か(この場合は、JVM)がメモリの割り当てと解放を処理する必要があることを意味します。メモリリークも過去のものになるはずです。CおよびC ++で記述された一部のアプリケーションは、プログラマーが適切なタイミングで不要なメモリを解放することに注意を払わないため、ふるいのようにメモリリークが発生することで悪名高くなっています。ガベージコレクションは、メモリの問題のデバッグに費やす時間が減り、プログラマーの生産性も向上します。
リテラルのポインタも持つことができます。自分で実装する必要があります。エキスパートにとっては非常に基本的なことです;)。int / object / long / byteの配列を使用して、ポインタを実装するための基本を確認します。これで、任意のint値がその配列int []へのポインターになることができます。ポインターをインクリメントしたり、ポインターをデクリメントしたり、ポインターを乗算したりできます。あなたは確かにポインター算術を持っています!これが、1000個のint属性クラスを実装し、すべての属性に適用されるジェネリックメソッドを持つ唯一の方法です。int []の代わりにbyte []配列を使用することもできます
ただし、Javaでリテラル値を参照渡しできるようにしたいと思います。線に沿った何か
//(* telling you it is a pointer)
public void myMethod(int* intValue);