web-dev-qa-db-fra.com

En quoi une référence Java Java est-elle différente d'un pointeur C?

C a des pointeurs et Java a ce qu'on appelle des références. Ils ont certaines choses en commun dans le sens où ils pointent tous vers quelque chose. Je sais que les pointeurs en C stockent les adresses vers lesquelles ils pointent. Do référence stocke également l'adresse? Comment sont-ils différents, sauf que le pointeur est plus flexible et sujet aux erreurs?

97
Gnijuohz

Les références peuvent être implémentées en stockant l'adresse. Habituellement Java les références seront implémentées comme pointeurs, mais ce n'est pas requis par la spécification. Ils peuvent utiliser une couche supplémentaire d'indirection pour faciliter la collecte des ordures. Mais au final, cela se résumera (presque toujours) à des pointeurs (de style C) impliqués dans l'implémentation de (Style Java) références.

Vous ne pouvez pas faire d'arithmétique de pointeur avec des références. La différence la plus importante entre un pointeur en C et une référence en Java est que vous ne pouvez pas réellement accéder à ( et manipuler) la valeur sous-jacente d'une référence en Java. En d'autres termes: vous ne pouvez pas faire de l'arithmétique des pointeurs.

En C, vous pouvez ajouter quelque chose à un pointeur (c'est-à-dire l'adresse) ou soustraire quelque chose pour pointer vers des choses qui sont "à proximité" ou pointer vers des endroits qui sont à tout endroit.

En Java, une référence pointe vers une seule chose et cette seule chose. Vous pouvez faire en sorte qu'une variable contienne une référence différente , mais vous ne pouvez pas simplement lui demander de pointer "la chose après la chose d'origine".

Les références sont fortement typées. Une autre différence est que le type d'une référence est beaucoup plus strictement contrôlé dans Java que le type d'un pointeur est en C. En C, vous pouvez avoir un int* et le convertir en char* et juste réinterpréter la mémoire à cet endroit. Cette réinterprétation ne fonctionne pas en Java: vous ne pouvez interpréter l'objet à l'autre extrémité de la référence que comme quelque chose qu'il est déjà (ie vous pouvez convertir une référence Object à une référence String uniquement si l'objet pointé est en fait un String).

Ces différences rendent les pointeurs C plus puissants, mais aussi plus dangereux. Ces deux possibilités (arithmétique du pointeur et réinterprétation des valeurs pointées) ajoutent de la flexibilité à C et sont la source d'une partie de la puissance de la langue. Mais ils sont également de grandes sources de problèmes, car s'ils sont mal utilisés, ils peuvent facilement casser les hypothèses selon lesquelles votre code est construit. Et il est assez facile de les utiliser incorrectement.

142
Joachim Sauer

Les références C++ sont à nouveau différentes.

Ils doivent être initialisés et ne peuvent pas être nuls (du moins pas dans un programme bien formé) et ne peuvent pas être réinstallés pour faire référence à autre chose. une référence C++ ressemble beaucoup plus à un alias pour un objet.

Une autre différence importante entre les pointeurs et les références Java/C++ est que vous pouvez prendre l'adresse d'un pointeur auquel vous ne pouvez pas accéder à l'adresse d'une référence (en effet, une référence C++ n'a pas besoin d'exister réellement en tant qu'objet en mémoire du tout) par conséquent, vous pouvez avoir un pointeur vers un pointeur mais pas une référence à une référence

7
jk.

Les références Java et les pointeurs C diffèrent sur exactement deux points:

  1. Il n'y a pas d'arithmétique de pointeur pour le premier.
  2. Et vous ne pouvez pas créer une référence Java à tout ce que vous voulez, vous ne pouvez copier que celles enregistrées dans un endroit accessible (champs statiques, champs d'objets, variables locales) ou renvoyées par des invocations de fonctions (comme constructeur- appels), qui font donc tous référence à Java (jamais aux types de base comme les références, char, int et ainsi de suite).

Quelqu'un a écrit que les références sont fortement typées, car vous ne pouvez pas forcer le compilateur à traiter un int* comme un char*.
En dehors du fait que cette conversion particulière est en fait sûre , il n'y a pas de polymorphisme en C, de sorte que la comparaison est non-starter.
Certes, Java est plus typé que C, pas que ce soit une caractéristique des pointeurs C vs Java références, vous devez utiliser le JNI pour briser la sécurité de type (en plus de ne pas tenir compte des restrictions génériques), mais même en C, vous devez forcer le compilateur.

Quelqu'un a écrit que Java pourraient être implémentées en tant que pointeurs C, auxquels je dis bien sûr, car elles sont strictement moins puissantes, sur les machines 32 bits, elles le sont généralement, si la machine virtuelle Java est implémentée en C . Bien que sur les machines 64 bits, elles soient normalement pointeurs d'objets ordinaires compressés ("POO compressés") pour économiser de l'espace et de la bande passante.
Quoi qu'il en soit, ces pointeurs C ne doivent pas non plus être équivalents à des adresses matérielles, même si elles sont généralement (> 99% des implémentations) pour des raisons de performances.
Enfin, c'est un détail d'implémentation qui n'est pas exposé au programmeur.

4
Deduplicator