So che Java non ha puntatori, ma ho sentito che i programmi Java possono essere creati con puntatori e che questo può essere fatto dai pochi esperti in Java. È vero?
So che Java non ha puntatori, ma ho sentito che i programmi Java possono essere creati con puntatori e che questo può essere fatto dai pochi esperti in Java. È vero?
Risposte:
Tutti gli oggetti in Java sono riferimenti e puoi usarli come puntatori.
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;
Dereferenziare un null:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
Problema di aliasing:
third = new Tiger();
first = third;
Perdere cellule:
second = third; // Possible ERROR. The old value of second is lost.
Puoi renderlo sicuro assicurandoti prima che non ci sia più bisogno del vecchio valore di second o assegnando a un altro puntatore il valore di second.
first = second;
second = third; //OK
Si noti che dare a secondo un valore in altri modi (NULL, nuovo ...) è altrettanto un potenziale errore e può comportare la perdita dell'oggetto a cui punta.
Il sistema Java genererà un'eccezione ( OutOfMemoryError
) quando si chiama new e l'allocatore non può allocare la cella richiesta. Questo è molto raro e di solito è il risultato di una ricorsione di fuga.
Si noti che, dal punto di vista del linguaggio, abbandonare oggetti al garbage collector non sono affatto errori. È solo qualcosa di cui il programmatore deve essere consapevole. La stessa variabile può puntare a oggetti diversi in momenti diversi e i vecchi valori verranno recuperati quando nessun puntatore vi fa riferimento. Ma se la logica del programma richiede il mantenimento di almeno un riferimento all'oggetto, causerà un errore.
I novizi spesso commettono il seguente errore.
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
Quello che probabilmente intendevi dire era:
Tiger tony = null;
tony = third; // OK.
Casting improprio:
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.
Puntatori 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
}
Puntatori 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
}
}
AGGIORNAMENTO: come suggerito nei commenti si deve notare che il C ha aritmetica dei puntatori. Tuttavia, non lo abbiamo in Java.
Java ha dei puntatori. Ogni volta che crei un oggetto in Java, stai effettivamente creando un puntatore all'oggetto; questo puntatore potrebbe quindi essere impostato su un oggetto diverso o su null
, e l'oggetto originale esisterà ancora (in attesa di garbage collection).
Quello che non puoi fare in Java è l'aritmetica dei puntatori. Non è possibile dereferenziare un indirizzo di memoria specifico o incrementare un puntatore.
Se vuoi davvero ottenere un livello basso, l'unico modo per farlo è con Java Native Interface ; e anche allora, la parte di basso livello deve essere eseguita in C o C ++.
Poiché Java non ha tipi di dati del puntatore, è impossibile utilizzare i puntatori in Java. Anche i pochi esperti non saranno in grado di utilizzare i puntatori in java.
Vedi anche l'ultimo punto in: The Java Language Environment
Ci sono puntatori in Java, ma non puoi manipolarli nel modo in cui puoi farlo in C ++ o C. Quando passi un oggetto, stai passando un puntatore a quell'oggetto, ma non nello stesso senso come in C ++. Quell'oggetto non può essere dereferenziato. Se imposti i suoi valori utilizzando le sue funzioni di accesso native, cambierà perché Java conosce la sua posizione di memoria tramite il puntatore. Ma il puntatore è immutabile. Quando si tenta di impostare il puntatore in una nuova posizione, si finisce invece con un nuovo oggetto locale con lo stesso nome dell'altro. L'oggetto originale rimane invariato. Ecco un breve programma per dimostrare la differenza.
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;
}
}
Questo può essere eseguito su Ideone.com.
Java non ha puntatori come quelli del C, ma consente di creare nuovi oggetti sull'heap a cui fanno riferimento le variabili. La mancanza di puntatori impedisce ai programmi Java di fare riferimento illegalmente a posizioni di memoria e consente inoltre di eseguire automaticamente la Garbage Collection da parte della Java Virtual Machine.
È possibile utilizzare indirizzi e puntatori utilizzando la classe Unsafe. Tuttavia, come suggerisce il nome, questi metodi sono NON SICURI e generalmente una cattiva idea. Un utilizzo errato può causare la morte casuale della tua JVM (in realtà lo stesso problema si ottiene utilizzando i puntatori in modo errato in C / C ++)
Sebbene tu possa essere abituato ai puntatori e pensare di averne bisogno (perché non sai come codificare in nessun altro modo), scoprirai che non lo fai e starai meglio per questo.
Tecnicamente, tutti gli oggetti Java sono puntatori. Tuttavia, tutti i tipi primitivi sono valori. Non è possibile assumere il controllo manuale di tali puntatori. Java utilizza solo internamente il passaggio per riferimento.
Non proprio no.
Java non ha puntatori. Se davvero lo volessi, potresti provare a emularli costruendo attorno a qualcosa come il riflesso, ma avrebbe tutta la complessità dei puntatori senza nessuno dei vantaggi .
Java non ha puntatori perché non ne ha bisogno. Che tipo di risposte speravi da questa domanda, cioè in fondo speravi di poterle usare per qualcosa o era solo curiosità?
Tutti gli oggetti in java vengono passati alle funzioni tramite copia di riferimento tranne le primitive.
In effetti, questo significa che stai inviando una copia del puntatore all'oggetto originale piuttosto che una copia dell'oggetto stesso.
Per favore lascia un commento se vuoi un esempio per capirlo.
swap
funzione in Java che scambierà due oggetti.
Come altri hanno già detto, la risposta breve è "No".
Certo, potresti scrivere codice JNI che gioca con i puntatori Java. A seconda di ciò che stai cercando di realizzare, forse questo ti porterebbe da qualche parte e forse no.
È sempre possibile simulare i punti creando un array e lavorando con gli indici nell'array. Di nuovo, a seconda di ciò che stai cercando di realizzare, potrebbe o non potrebbe essere utile.
dal libro Decompiling Android di Godfrey Nolan
La sicurezza impone che i puntatori non vengano utilizzati in Java, quindi gli hacker non possono uscire da un'applicazione e entrare nel sistema operativo. Nessun puntatore significa che qualcos'altro, in questo caso, la JVM, deve occuparsi dell'allocazione e della liberazione della memoria. Anche le perdite di memoria dovrebbero diventare un ricordo del passato, o almeno così dice la teoria. Alcune applicazioni scritte in C e C ++ sono note per perdere memoria come un setaccio perché i programmatori non prestano attenzione a liberare memoria indesiderata al momento opportuno - non che chiunque legga questo sarebbe colpevole di un tale peccato. La raccolta dei rifiuti dovrebbe anche rendere i programmatori più produttivi, con meno tempo speso per il debug dei problemi di memoria.
puoi anche avere puntatori per letterali. Devi implementarli da solo. È piuttosto semplice per gli esperti;). Usa un array di int / object / long / byte e voilà hai le basi per l'implementazione dei puntatori. Ora qualsiasi valore int può essere un puntatore a quell'array int []. Puoi aumentare il puntatore, puoi decrementare il puntatore, puoi moltiplicare il puntatore. Hai davvero aritmetica dei puntatori! Questo è l'unico modo per implementare 1000 classi di attributi int e avere un metodo generico che si applica a tutti gli attributi. Puoi anche utilizzare un array byte [] invece di un int []
Tuttavia, vorrei che Java ti consentisse di passare valori letterali per riferimento. Qualcosa sulla falsariga
//(* telling you it is a pointer)
public void myMethod(int* intValue);
Tutti gli oggetti Java sono puntatori perché una variabile che contiene l'indirizzo è chiamata puntatore e l'oggetto contiene indirizzo.so l'oggetto è una variabile puntatore.