Ich weiß, dass Java keine Zeiger hat, aber ich habe gehört, dass Java-Programme mit Zeigern erstellt werden können und dass dies von den wenigen Experten in Java durchgeführt werden kann. Ist es wahr?
Ich weiß, dass Java keine Zeiger hat, aber ich habe gehört, dass Java-Programme mit Zeigern erstellt werden können und dass dies von den wenigen Experten in Java durchgeführt werden kann. Ist es wahr?
Antworten:
Alle Objekte in Java sind Referenzen und können wie Zeiger verwendet werden.
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;
Dereferenzieren einer Null:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
Aliasing-Problem:
third = new Tiger();
first = third;
Zellen verlieren:
second = third; // Possible ERROR. The old value of second is lost.
Sie können dies sicher machen, indem Sie zunächst sicherstellen, dass der alte Wert von second nicht mehr benötigt wird, oder einem anderen Zeiger den Wert von second zuweisen.
first = second;
second = third; //OK
Beachten Sie, dass das Geben eines zweiten Werts auf andere Weise (NULL, neu ...) ebenso ein potenzieller Fehler ist und zum Verlust des Objekts führen kann, auf das es zeigt.
Das Java-System löst eine Ausnahme ( OutOfMemoryError
) aus, wenn Sie new aufrufen und der Allokator die angeforderte Zelle nicht zuordnen kann. Dies ist sehr selten und resultiert normalerweise aus einer weggelaufenen Rekursion.
Beachten Sie, dass aus sprachlicher Sicht das Übergeben von Objekten an den Garbage Collector überhaupt keine Fehler sind. Es ist nur etwas, das der Programmierer beachten muss. Dieselbe Variable kann zu unterschiedlichen Zeiten auf unterschiedliche Objekte verweisen, und alte Werte werden zurückgefordert, wenn kein Zeiger auf sie verweist. Wenn die Logik des Programms jedoch die Aufrechterhaltung mindestens eines Verweises auf das Objekt erfordert, führt dies zu einem Fehler.
Anfänger machen häufig den folgenden Fehler.
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
Was Sie wahrscheinlich sagen wollten, war:
Tiger tony = null;
tony = third; // OK.
Unsachgemäßes Casting:
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.
Zeiger in 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
}
Zeiger in 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
}
}
UPDATE: Wie in den Kommentaren vorgeschlagen, muss man beachten, dass C Zeigerarithmetik hat. In Java gibt es das jedoch nicht.
Java hat Zeiger. Jedes Mal, wenn Sie ein Objekt in Java erstellen, erstellen Sie tatsächlich einen Zeiger auf das Objekt. Dieser Zeiger könnte dann auf ein anderes Objekt oder auf gesetzt werden null
, und das ursprüngliche Objekt bleibt bestehen (ausstehende Speicherbereinigung).
Was Sie in Java nicht tun können, ist Zeigerarithmetik. Sie können eine bestimmte Speicheradresse nicht dereferenzieren oder einen Zeiger erhöhen.
Wenn Sie wirklich auf niedrigem Niveau arbeiten möchten, können Sie dies nur mit der Java Native Interface tun . und selbst dann muss der Low-Level-Teil in C oder C ++ erledigt werden.
Da Java keine Zeigerdatentypen hat, ist es unmöglich, Zeiger in Java zu verwenden. Selbst die wenigen Experten werden in Java keine Zeiger verwenden können.
Siehe auch den letzten Punkt in: Die Java-Sprachumgebung
In Java gibt es Zeiger, aber Sie können sie nicht wie in C ++ oder C bearbeiten. Wenn Sie ein Objekt übergeben, übergeben Sie einen Zeiger auf dieses Objekt, jedoch nicht im gleichen Sinne wie in C ++. Dieses Objekt kann nicht dereferenziert werden. Wenn Sie die Werte mit den nativen Zugriffsmethoden festlegen, ändert sich dies, da Java den Speicherort über den Zeiger kennt. Aber der Zeiger ist unveränderlich. Wenn Sie versuchen, den Zeiger auf einen neuen Speicherort zu setzen, erhalten Sie stattdessen ein neues lokales Objekt mit demselben Namen wie das andere. Das ursprüngliche Objekt bleibt unverändert. Hier ist ein kurzes Programm, um den Unterschied zu demonstrieren.
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;
}
}
Dies kann auf Ideone.com ausgeführt werden.
Java hat keine Zeiger wie C, aber Sie können neue Objekte auf dem Heap erstellen, auf die durch Variablen "verwiesen" wird. Das Fehlen von Zeigern verhindert, dass Java-Programme illegal auf Speicherorte verweisen, und ermöglicht außerdem, dass die Garbage Collection automatisch von der Java Virtual Machine ausgeführt wird.
Sie können Adressen und Zeiger mit der Klasse Unsafe verwenden. Wie der Name schon sagt, sind diese Methoden UNSICHER und im Allgemeinen eine schlechte Idee. Eine falsche Verwendung kann dazu führen, dass Ihre JVM zufällig stirbt (tatsächlich führt das gleiche Problem dazu, dass Zeiger in C / C ++ falsch verwendet werden).
Während Sie vielleicht an Zeiger gewöhnt sind und denken, dass Sie sie brauchen (weil Sie nicht wissen, wie man auf andere Weise codiert), werden Sie feststellen, dass Sie dies nicht tun, und Sie werden besser dran sein.
Technisch gesehen sind alle Java-Objekte Zeiger. Alle primitiven Typen sind jedoch Werte. Es gibt keine Möglichkeit, diese Zeiger manuell zu steuern. Java verwendet nur intern Pass-by-Reference.
Nicht wirklich, nein.
Java hat keine Zeiger. Wenn Sie wirklich wollten, könnten Sie versuchen, sie zu emulieren, indem Sie sich auf etwas wie Reflexion stützen, aber es hätte die ganze Komplexität von Zeigern ohne die Vorteile .
Java hat keine Zeiger, weil es sie nicht benötigt. Auf welche Art von Antworten haben Sie von dieser Frage gehofft, dh tief im Inneren haben Sie gehofft, Sie könnten sie für etwas verwenden, oder war das nur Neugier?
Alle Objekte in Java werden per Referenzkopie an Funktionen übergeben, mit Ausnahme von Grundelementen.
In der Tat bedeutet dies, dass Sie eine Kopie des Zeigers auf das ursprüngliche Objekt und nicht auf eine Kopie des Objekts selbst senden.
Bitte hinterlassen Sie einen Kommentar, wenn Sie möchten, dass ein Beispiel dies versteht.
swap
in Java keine Funktion schreiben, die zwei Objekte austauscht.
Wie andere gesagt haben, lautet die kurze Antwort "Nein".
Sicher, Sie könnten JNI-Code schreiben, der mit Java-Zeigern spielt. Je nachdem, was Sie erreichen möchten, bringt Sie das vielleicht irgendwohin und vielleicht auch nicht.
Sie können Punkte jederzeit simulieren, indem Sie ein Array erstellen und mit Indizes im Array arbeiten. Je nachdem, was Sie erreichen möchten, kann dies wiederum nützlich sein oder auch nicht.
aus dem Buch Decompiling Android von Godfrey Nolan
Die Sicherheit schreibt vor, dass Zeiger in Java nicht verwendet werden, damit Hacker nicht aus einer Anwendung in das Betriebssystem eindringen können. Keine Zeiger bedeuten, dass sich etwas anderes - in diesem Fall die JVM - um das Zuweisen und Freigeben von Speicher kümmern muss. Speicherlecks sollten ebenfalls der Vergangenheit angehören, so die Theorie. Einige in C und C ++ geschriebene Anwendungen sind dafür berüchtigt, Speicher wie ein Sieb zu verlieren, da Programmierer nicht darauf achten, unerwünschten Speicher zum richtigen Zeitpunkt freizugeben ---- nicht, dass jemand, der dies liest, einer solchen Sünde schuldig wäre. Die Speicherbereinigung sollte Programmierer auch produktiver machen und weniger Zeit für das Debuggen von Speicherproblemen aufwenden.
Sie können auch Zeiger für Literale haben. Sie müssen sie selbst implementieren. Für Experten ist es ziemlich einfach;). Verwenden Sie ein Array aus int / object / long / byte und voila. Sie haben die Grundlagen für die Implementierung von Zeigern. Jetzt kann jeder int-Wert ein Zeiger auf dieses Array int [] sein. Sie können den Zeiger inkrementieren, Sie können den Zeiger dekrementieren, Sie können den Zeiger multiplizieren. Sie haben tatsächlich Zeigerarithmetik! Nur so können 1000 int-Attributklassen implementiert und eine generische Methode verwendet werden, die für alle Attribute gilt. Sie können auch ein Byte [] -Array anstelle eines int [] verwenden.
Ich wünschte jedoch, Java würde es Ihnen ermöglichen, Literalwerte als Referenz zu übergeben. Etwas in der Richtung
//(* telling you it is a pointer)
public void myMethod(int* intValue);
Alle Java-Objekte sind Zeiger, da eine Variable, die die Adresse enthält, als Zeiger und das Objekt als Adresse bezeichnet wird. Das Objekt ist also eine Zeigervariable.