web-dev-qa-db-fra.com

Comment utiliser des pointeurs en Java?

Je sais que Java n'a pas de pointeur, mais j'ai entendu dire que Java, les programmes peuvent être créés avec des pointeurs et que cela peut être fait par les quelques experts en Java. Est-ce vrai?

98
user213038

Tous les objets dans Java sont des références et vous pouvez les utiliser comme des pointeurs.

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;

Déréférencer un null:

first.growl();  // ERROR, first is null.    
third.growl(); // ERROR, third has not been initialized.

Problème d'aliasing:

third = new Tiger();
first = third;

Perdre des cellules:

second = third; // Possible ERROR. The old value of second is lost.    

Vous pouvez sécuriser cela en s'assurant d’abord que l’ancienne valeur de second n’est plus nécessaire ou en affectant à un autre pointeur la valeur de second.

first = second;
second = third; //OK

Notez que donner une autre valeur à second (NULL, new ...) est tout aussi une erreur potentielle et peut entraîner la perte de l'objet sur lequel il pointe.

Le système Java lève une exception (OutOfMemoryError) lorsque vous appelez new et que l'allocateur ne peut pas allouer la cellule demandée. Ceci est très rare et résulte généralement d'une récursion fugitive.

Notez que, du point de vue du langage, abandonner des objets au garbage collector n'est pas du tout une erreur. C'est simplement quelque chose que le programmeur doit connaître. La même variable peut pointer sur différents objets à différentes heures et les anciennes valeurs seront récupérées si aucun pointeur ne les fait référence. Mais si la logique du programme nécessite de conserver au moins une référence à l'objet, cela provoquera une erreur.

Les novices font souvent l'erreur suivante.

Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed. 

Ce que vous vouliez dire probablement était:

Tiger tony = null;
tony = third; // OK.

Casting incorrect:

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.

Pointeurs en 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
}

Pointeurs en 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
    }
} 

PDATE: Comme suggéré dans les commentaires, il faut noter que C est arithmétique de pointeur. Cependant, nous n'avons pas cela en Java.

233
Sajad Bahmani

Java a des pointeurs. Chaque fois que vous créez un objet en Java, vous créez en fait un pointeur sur cet objet. ce pointeur pourrait alors être défini sur un autre objet ou sur null, et l'objet d'origine existera toujours (garbage collection en attente).

Ce que vous ne pouvez pas faire dans Java est une arithmétique de pointeur. Vous ne pouvez pas déréférencer une adresse mémoire spécifique ou incrémenter un pointeur.

Si vous voulez vraiment avoir un niveau bas, la seule façon de le faire est avec Interface native Java ; et même alors, la partie de bas niveau doit être faite en C ou C++.

42
Michael Myers

Comme Java n'a pas de type de données de pointeur, il est impossible d'utiliser des pointeurs en Java. Même les quelques experts ne seront pas en mesure d'utiliser des pointeurs en Java.

Voir aussi le dernier point dans: L'environnement de langage Java

30
Fortega

Java n'a pas de pointeurs similaires à ceux de C, mais il vous permet de créer de nouveaux objets sur le tas, qui sont "référencés" par des variables. L'absence de pointeurs empêche les programmes Java de référencer illégalement des emplacements mémoire et permet également à Garbage Collection d'être automatiquement effectué par la machine virtuelle Java.

9
Zubair

Vous pouvez utiliser des adresses et des pointeurs à l'aide de la classe Unsafe. Cependant, comme le nom l’indique, ces méthodes sont sans fondement et sont en général une mauvaise idée. Une utilisation incorrecte peut entraîner la mort aléatoire de votre machine virtuelle (le même problème survient lorsque les pointeurs sont mal utilisés en C/C++).

Bien que vous soyez habitué aux pointeurs et que vous pensiez en avoir besoin (car vous ne savez pas coder autrement), vous constaterez que vous n'en avez pas besoin et que vous en tirerez mieux.

7
Peter Lawrey

Il existe des pointeurs en Java, mais vous ne pouvez pas les manipuler comme vous pouvez le faire en C++ ou en C. Lorsque vous transmettez un objet, vous passez un pointeur sur cet objet, mais pas dans le même sens qu'en C++. Cet objet ne peut pas être déréférencé. Si vous définissez ses valeurs à l'aide de ses accesseurs natifs, cela changera car Java connaît son emplacement de mémoire via le pointeur. Mais le pointeur est immuable. Lorsque vous essayez de définir le pointeur sur un nouvel emplacement, vous vous retrouvez avec un nouvel objet local portant le même nom que l'autre. L'objet d'origine est inchangé. Voici un bref programme pour démontrer la différence.

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;
    }
}

Cela peut être exécuté sur Ideone.com.

7
kingfrito_5005

Tous les objets dans Java sont transmis aux fonctions par copie de référence, à l'exception des primitives.

En effet, cela signifie que vous envoyez une copie du pointeur à l'objet d'origine plutôt qu'une copie de l'objet lui-même.

S'il vous plaît laissez un commentaire si vous voulez un exemple pour comprendre cela.

3
coolest_head

Les types de référence Java ne sont pas identiques aux pointeurs C, car vous ne pouvez pas avoir de pointeur sur un pointeur en Java.

2
zezba9000

Techniquement, tous les objets Java sont des pointeurs. Tous les types primitifs sont des valeurs cependant. Il n'y a aucun moyen de prendre le contrôle manuel de ces pointeurs. Java utilise uniquement en interne le passage par référence.

1
Poindexter

Non, pas vraiment.

Java n'a pas de pointeurs. Si vous vouliez vraiment , vous pouvez essayer de les imiter en construisant autour de quelque chose qui ressemble à de la réflexion, mais cela aurait tous les complexité des pointeurs avec aucun des avantages.

Java n'a pas de pointeur car il n'en a pas besoin. Quel genre de réponses espériez-vous de cette question, c’est-à-dire que vous espériez pouvoir les utiliser pour quelque chose ou était-ce une simple curiosité?

1
Andrzej Doyle

extrait du livre intitulé Decompiling Android de Godfrey Nolan

La sécurité impose que les pointeurs ne sont pas utilisés en Java afin que les pirates informatiques ne puissent pas sortir d’une application et entrer dans le système d’exploitation. Aucun pointeur ne signifie que quelque chose d'autre ---- dans ce cas, la JVM ---- doit s'occuper de l'allocation et de la libération de la mémoire. Les fuites de mémoire devraient également appartenir au passé, du moins selon la théorie. Certaines applications écrites en C et C++ sont réputées pour fuir la mémoire comme un tamis, car les programmeurs ne font pas attention à libérer de la mémoire non désirée au moment approprié. La récupération de place devrait également rendre les programmeurs plus productifs, avec moins de temps consacré au débogage des problèmes de mémoire.

1
Mustafa Güven

Comme d'autres l'ont dit, la réponse courte est "non".

Bien sûr, vous pourriez écrire du code JNI qui joue avec les pointeurs Java. En fonction de ce que vous essayez d'accomplir, cela vous mènera peut-être quelque part et peut-être que non.

Vous pouvez toujours simuler des pointes en créant un tableau et en utilisant des index dans le tableau. Encore une fois, selon ce que vous essayez d'accomplir, cela pourrait être utile ou non.

0
Jay

vous pouvez également avoir des indicateurs pour les littéraux. Vous devez les mettre en œuvre vous-même. C'est assez basique pour les experts;). Utilisez un tableau de int/object/long/byte et le tour est joué, vous avez les bases pour implémenter des pointeurs. Maintenant, toute valeur int peut être un pointeur sur ce tableau int []. Vous pouvez incrémenter le pointeur, vous pouvez décrémenter le pointeur, vous pouvez multiplier le pointeur. Vous avez en effet des arithmétiques de pointeur! C'est la seule façon d'implémenter 1000 classes d'attributs int et d'avoir une méthode générique qui s'applique à tous les attributs. Vous pouvez également utiliser un tableau d'octets [] au lieu d'un entier []

Cependant, je souhaite que Java vous laisse passer des valeurs littérales par référence. Quelque chose le long des lignes

//(* telling you it is a pointer) public void myMethod(int* intValue);

0
Mordan