Comment puis-je utiliser des pointeurs en Java?


112

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


1
Dans l'implémentation de Sun de toute façon.
Michael Myers

1
puis-je utiliser cette adresse de pointeur

6
Le hashCode par défaut pour un objet java n'est PAS son adresse de pointeur, relisez attentivement le contrat pour hashCode et vous remarquerez que deux objets distincts en mémoire peuvent avoir la même valeur de hashCode.
Amir Afghani

3
Dans Java 64 bits et 32 ​​bits, le hashCode 32 bits n'est pas l'adresse. Il n'est pas garanti que les hashCodes soient uniques. L'emplacement d'un objet peut être déplacé en mémoire lors de son déplacement entre les espaces et la mémoire est compactée, le hashCode ne change cependant pas.
Peter Lawrey

2
90% de ce que vous pouvez faire avec des pointeurs C ++, vous pouvez le faire avec des réfrences Java, les 10% restants que vous pouvez obtenir en empaquetant une référence dans un autre objet (pas que je n'ai jamais trouvé nécessaire de faire cela)
Richard Tingle

Réponses:


243

Tous les objets en 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 vous assurant d'abord qu'il n'y a plus besoin de l'ancienne valeur de second ou en attribuant à un autre pointeur la valeur de second.

first = second;
second = third; //OK

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

Le système Java lèvera 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écursivité fugitive.

Notez que, du point de vue du langage, abandonner des objets au ramasse-miettes ne sont pas du tout des erreurs. C'est juste quelque chose dont le programmeur doit être conscient. La même variable peut pointer vers différents objets à des moments différents et les anciennes valeurs seront récupérées lorsqu'aucun pointeur ne les référencera. 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 probablement dire é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
    }
} 

UPDATE: comme suggéré dans les commentaires, il faut noter que C a une arithmétique de pointeur. Cependant, nous n'avons pas cela en Java.


16
Bonne réponse, mais vous n'avez pas réussi à aborder une différence clé: C a une arithmétique de pointeur. (Heureusement) vous ne pouvez pas faire cela en Java.
R. Martinho Fernandes

10
Je déteste voter contre toute réponse, en particulier celle qui est populaire, mais Java n'a pas de pointeurs et vous ne pouvez tout simplement pas utiliser une référence comme un pointeur. Il y a certaines choses que vous ne pouvez faire qu'avec de vrais pointeurs - par exemple, vous pouvez obtenir ou définir n'importe quel octet dans votre espace de données de processus. Vous ne pouvez tout simplement pas faire cela en Java. C'est vraiment dommage que tant de gens ici semblent ne pas comprendre ce qu'est vraiment un pointeur, à mon humble avis, et maintenant je vais sortir de ma boîte à savon et j'espère que vous me pardonnerez pour ma petite explosion.
Danger

5
Je pense que tu veux dire Malheureusement. Pourquoi pensez-vous qu'il est bon que java ne prenne pas en charge l'arithmétique des pointeurs?
user3462295

2
@ user3462295 Parce que les gens semblent penser qu'il est trop difficile à utiliser par la population en général, et ne peut être compris qu'en codant des ninjas écrivant des compilateurs ou des pilotes de périphériques.
iCodeSometime

4
@Danger Première ligne de réponse "Tous les objets en Java sont des références et vous pouvez les utiliser comme des pointeurs.". C'est la meilleure réponse qui puisse être fournie. Si la seule réponse avait été "Non, java n'a pas de pointeurs." cette réponse n'aurait pas été utile. Cette réponse indique plutôt ce que vous pouvez faire à la place.
csga5000

46

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

Ce que vous ne pouvez pas faire en Java, c'est l'arithmétique des pointeurs. Vous ne pouvez pas déréférencer une adresse mémoire spécifique ou incrémenter un pointeur.

Si vous voulez vraiment obtenir de bas niveau, la seule façon de le faire est d'utiliser l' interface native Java ; et même alors, la partie de bas niveau doit être effectuée en C ou C ++.


9
Java n'a tout simplement pas de pointeurs, clairs et simples, et je ne peux pas pour la vie de moi comprendre pourquoi tant de réponses ici indiquent des informations incorrectes. Ce sont les gens de StackOverlfow! La définition d'un pointeur en informatique est (vous pouvez Google pour cela): "En informatique, un pointeur est un objet de langage de programmation, dont la valeur fait référence (ou" pointe vers ") une autre valeur stockée ailleurs dans la mémoire de l'ordinateur en utilisant son adresse. " Une référence en Java n'est PAS un pointeur. Java doit exécuter le ramasse-miettes et si vous aviez un vrai pointeur, ce serait faux!
Danger

3
@Danger Un pointeur est une donnée contenant une adresse mémoire. Java est deux choses que les gens oublient. C'est une langue et une plateforme. Bien que l'on ne dise pas que .NET est un langage, nous devons nous rappeler que dire «Java n'a pas de pointeurs» peut être trompeur car la plate-forme a et utilise bien sûr des pointeurs. Ces pointeurs ne sont pas accessibles au programmeur via le langage Java, mais ils existent dans le runtime. Les références dans le langage existent au-dessus des pointeurs réels dans le runtime.
kingfrito_5005

@ kingfrito_5005 Il semblerait que vous soyez d'accord avec moi. Je crois que vous avez dit "Ces pointeurs ne sont pas accessibles au programmeur via le langage Java", ce qui est cohérent avec ma déclaration selon laquelle "Java n'a pas de pointeurs". Les références sont sémantiquement significativement différentes des pointeurs.
Danger

1
@Danger c'est vrai, mais je pense qu'il est important dans ces cas de faire la distinction entre la plate-forme et le langage parce que je sais que lorsque j'ai commencé, une déclaration comme la vôtre m'aurait confondu.
kingfrito_5005

1
Oui, Java a certainement des pointeurs derrière les variables. C'est juste que les développeurs n'ont pas à les gérer parce que java fait la magie pour cela dans les coulisses. Cela signifie que les développeurs ne sont pas directement autorisés à pointer une variable vers une adresse de mémoire spécifique, et à gérer les décalages de données et autres. Cela permet à java de garder un ramasse-miettes memmory propre, mais comme chaque variable est essentiellement un pointeur, il faut également un peu de mémoire supplémentaire pour avoir toutes ces adresses de pointeur générées automatiquement, ce qui dans les langages plus bas niveau aurait pu être évité.
VulstaR

38

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

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


3
L'une des rares réponses correctes ici n'a pratiquement pas de votes positifs?
Danger

Notez qu'il existe des objets «pointeur» qui simulent un comportement semblable à un pointeur. À de nombreuses fins, cela peut être utilisé de la même manière, sans tenir compte de l'adressage du niveau de mémoire. Étant donné la nature de la question, je trouve étrange que personne d'autre ne l'ait mentionné.
kingfrito_5005

Cela devrait être la réponse en haut. Parce que pour les débutants, dire que "dans les coulisses java ont des pointeurs" peut conduire à un état très déroutant. Même lorsque Java est enseigné au niveau de départ, on apprend que les pointeurs ne sont pas sécurisés, c'est pourquoi ils ne sont pas utilisés en Java. Un programmeur a besoin de savoir ce qu'il peut voir et ce sur quoi il peut travailler. La référence et les pointeurs sont en fait très différents.
Neeraj Yadav

Pas sûr que je sois entièrement d'accord avec la rubrique "2.2.3 Pas d'énumérations" dans le lien. Les données peuvent être obsolètes, mais Java prend en charge les énumérations.
Sometowngeek

1
@Sometowngeek auquel le document lié est un livre blanc de 1996 décrivant la toute première version de java. Les énumérations sont introduites dans la version java 1.5 (2004)
Fortega

11

Il existe des pointeurs en Java, mais vous ne pouvez pas les manipuler comme vous le pouvez en C ++ ou C. Lorsque vous passez un objet, vous passez un pointeur vers 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 mémoire via le pointeur. Mais le pointeur est immuable. Lorsque vous essayez de définir le pointeur vers un nouvel emplacement, vous vous retrouvez à la place 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.


10

Java n'a pas de pointeurs comme C, mais il vous permet de créer de nouveaux objets sur le tas qui sont "référencés" par des variables. Le manque de pointeurs empêche les programmes Java de référencer illégalement des emplacements mémoire et permet également d'effectuer automatiquement le nettoyage de la mémoire par la machine virtuelle Java.


7

Vous pouvez utiliser des adresses et des pointeurs à l'aide de la classe Unsafe. Cependant, comme son nom l'indique, ces méthodes ne sont pas sûres et sont généralement une mauvaise idée. Une utilisation incorrecte peut entraîner la mort de votre JVM de manière aléatoire (en fait, le même problème est lié à l'utilisation incorrecte des pointeurs en C / C ++)

Bien que vous soyez habitué aux pointeurs et que vous pensez en avoir besoin (parce que vous ne savez pas coder autrement), vous constaterez que vous ne le faites pas et que vous serez mieux lotis.


8
Les pointeurs sont extrêmement puissants et utiles. Il existe de nombreux cas où le fait de ne pas avoir de pointeurs (Java) rend le code beaucoup moins efficace. Ce n'est pas parce que les gens sont nuls à utiliser des pointeurs que les langues devraient les exclure. Ne devrais-je pas avoir de fusil parce que d'autres (comme les militaires) les utilisent pour tuer des gens?
Ethan Reesor

1
Il n'y a pas grand chose d'utile ou de puissant que vous ne pouvez pas faire en Java comme l'est le langage. Pour tout le reste, il y a la classe Unsafe que je trouve que je dois utiliser très rarement.
Peter Lawrey

2
Une grande partie du code que j'ai écrit au cours des 40 dernières années n'aurait jamais pu être implémentée en Java, car Java manque de fonctionnalités de base et de bas niveau.
Danger

1
@Danger c'est pourquoi un grand nombre de bibliothèques utilisent Unsafe et l'idée de le supprimer a suscité tant de débats dans Java 9. Le plan est de fournir des remplacements, mais ils ne sont pas encore prêts.
Peter Lawrey

3

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


1
Pas même via JNI? Aucune connaissance de Java à proprement parler ici, mais je pensais avoir entendu dire que vous pouviez faire un peu d'essorage de bas niveau de cette façon.
David Seiler

Pour autant que mes ~ 4 ans d'expérience Java et que je cherche moi-même la réponse dit non, les pointeurs Java ne sont pas accessibles de l'extérieur.
Poindexter

Merci pour la réponse. J'ai demandé parce que, mon conférencier a dit qu'au niveau de la recherche où java était utilisé dans les appareils portables, ils utilisent le pointeur ... c'est pourquoi j'ai demandé

@unknown (google) si c'est au niveau de la recherche, en fonction de ce qui est fait, il se peut qu'ils aient eu besoin d'une telle fonctionnalité, ils ont donc violé les idiomes normaux et les ont quand même mis en œuvre. Vous pouvez implémenter votre propre JVM si vous souhaitez avoir un sur-ensemble (ou un sous-ensemble, ou un mélange) de fonctionnalités Java normales, mais ce code peut ne pas fonctionner sur d'autres plates-formes Java.
San Jacinto

@san: Merci pour la réponse. BTW, je ne peux pas voter .. dit que j'ai besoin de 15 réputation

2

Non, pas vraiment.

Java n'a pas de pointeurs. Si vous le vouliez vraiment, vous pourriez essayer de les imiter en construisant autour de quelque chose comme la réflexion, mais cela aurait toute la complexité des pointeurs sans aucun des avantages .

Java n'a pas de pointeurs car il n'en a pas besoin. Quel genre de réponses espériez-vous à cette question, c'est-à-dire au fond espérez-vous pouvoir les utiliser pour quelque chose ou était-ce juste de la curiosité?


Je suis curieux de le savoir. Merci pour la réponse

Java a besoin de pointeurs, et c'est pourquoi Java a ajouté JNI - pour contourner le manque de fonctions "de type pointeur" ou de niveau inférieur, vous ne pouvez tout simplement pas faire en Java, quel que soit le code que vous écrivez.
Danger

2

Tous les objets en java sont passés aux fonctions par copie de référence à l'exception des primitives.

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

Veuillez laisser un commentaire si vous voulez un exemple pour comprendre cela.


C'est tout simplement faux. Vous ne pouvez pas écrire une swapfonction en Java qui permutera deux objets.
Michael Tsang

2

Les types de référence Java ne sont pas les mêmes que les pointeurs C car vous ne pouvez pas avoir de pointeur vers un pointeur en Java.


1

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

Bien sûr, vous pouvez écrire du code JNI qui joue avec les pointeurs Java. Selon ce que vous essayez d'accomplir, cela vous mènerait peut-être quelque part et peut-être pas.

Vous pouvez toujours simuler des points 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.


1

extrait du livre intitulé Decompiling Android de Godfrey Nolan

La sécurité dicte que les pointeurs ne sont pas utilisés en Java afin que les pirates ne puissent pas sortir d'une application et entrer dans le système d'exploitation. Aucun pointeur signifie que quelque chose d'autre - dans ce cas, la JVM - doit s'occuper de l'allocation et de la libération de mémoire. Les fuites de mémoire devraient également devenir une chose du 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 parce que les programmeurs ne font pas attention à libérer de la mémoire indésirable au moment opportun - pas que quiconque lisant ceci serait coupable d'un tel péché. Le garbage collection devrait également rendre les programmeurs plus productifs, avec moins de temps consacré au débogage des problèmes de mémoire.


0

vous pouvez également avoir des pointeurs 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 voilà, vous avez les bases pour implémenter des pointeurs. Maintenant, toute valeur int peut être un pointeur vers 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 l'arithmétique des pointeurs! 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 int []

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

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


-1

Tous les objets java sont des pointeurs car une variable contenant une adresse est appelée pointeur et un objet contenant une adresse.so est une variable de pointeur.


1
Non, les objets Java ne sont pas des pointeurs. Ils sont équivalents à des références, qui ont un ensemble différent de capacités et de sémantiques.
Danger
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.