12
votes

Puis-je passer un type primitif par référence en Java?

Je voudrais appeler une méthode qui pourrait potentiellement prendre des versions différentes, c'est-à-dire la même méthode pour les paramètres d'entrée de type:

  • boolean li>
  • octet li>
  • court li>
  • int li>
  • long li> ul>

    La façon dont je voudrais faire cela est de "surcharger" la méthode (je pense que c'est le terme correct?): p>

    public void getValue(byte theByte) {...}
    public void getValue(short theShort) {...}
    ... etc ...
    


0 commentaires

9 Réponses :


5
votes

Vous ne pouvez pas. Dans les paramètres Java sont toujours passés par la valeur. Si le paramètre est un type de référence, la référence est transmise par la valeur et vous pouvez la modifier à l'intérieur de la méthode pendant les types primitifs, cela n'est pas possible.

Vous devrez créer un type d'emballage.


5 commentaires

Ok :( Comment créerais-je ce "type wrapper"? Pouvez-vous me montrer du code?


@Hristo, vous pouvez créer une classe qui tiendra le type primitif et transmettre cette classe à la méthode.


Hmmm d'accord. Je vais jeter un oeil à ça. Merci


L'utilisation de tels temps d'emballage a l'impression d'utiliser atomicboolcan , atomicinteger , etc. Sans le surcharge de simultanéisme / bloquant bien sûr.


@whiskeysierra si des cours boxés? Comme entier.



0
votes

Seulement en créant vos types de détention de votre valeur.


1 commentaires

Un type d'emballage est un objet contenant la valeur que vous souhaitez modifier. Ils sont souvent utilisés pour réunir des valeurs associées dans un seul objet pouvant être transmis plus facilement.



10
votes

Java est toujours passe-valeur . Il n'y a pas de transmission par référence en Java. Il est écrit dans les spécifications !


2 commentaires

Le Be Pedantic, il passe par la valeur de référence. Vous obtenez le même objet (pour les non-primitifs), mais vous ne pouvez pas modifier la référence réelle en dehors de votre propre portée.


Quel programmeur lirait les spécifications au lieu de le faire? C'est bien plus rapide d'aller pour une réponse à une telle question que de traverser les spécifications. Si un programmeur préfère passer par les spécifications pour une telle question, ce programmeur est assez inefficace.



1
votes

Les primitives ne sont pas transmises par des références (ou des objets pour cette affaire), donc non, vous ne pouvez pas.

int i = 1;
moo(i);
public void moo(int bah)
{
   bah = 3;
}
System.out.println(i);


1 commentaires

Oui, je comprends cela. Toute alternative?



1
votes

Les types d'objets de types primitifs en Java (double, entier, booléen, etc.) sont, si je me souviens bien, immuable. Cela signifie que vous ne pouvez pas modifier la valeur d'origine dans une méthode passée.

Il y a deux solutions à cela. L'un est de créer un type d'emballage qui contient la valeur. Si tout ce que vous essayez de faire est de modifier la valeur ou d'obtenir un calcul de la valeur, vous pourriez avoir la méthode renvoyer le résultat pour vous. Pour prendre vos exemples: xxx

et vous les appeleriez par les éléments suivants: xxx

ou quelque chose de similaire. Cela vous permet de muter ou de modifier la valeur et de renvoyer la valeur mutée, ce qui permettrait à quelque chose comme ce qui suit: xxx

espère que cela aide.


0 commentaires

9
votes

tandis que Java prend en charge la surcharge, tous les paramètres sont passés par la valeur, c'est-à-dire l'attribution d'un argument de méthode n'est pas visible pour l'appelant.

à partir de votre extrait de code, vous essayez de retourner une valeur de différents types. Étant donné que les types de retour ne font pas partie de la signature d'une méthode, vous ne pouvez pas surcharger avec différents types de retour. Par conséquent, l'approche habituelle est la suivante: xxx

S'il s'agit d'une conversion, la nommée standard est xxx


4 commentaires

+1 Ouais m'a battu. On dirait que l'objectif de l'OP est d'éviter cela, quand c'est un motif parfaitement commun et légitime.


Reportez-vous à ma mise à jour sur la raison pour laquelle j'essaie d'éviter cela. Il me semble maintenant que je vais juste finir par le faire de cette façon, mais cela mérite d'être demandé.


Oui, même lire votre mise à jour, je recommanderais mon approche. Les appelants doivent en quelque sorte spécifier le nombre de bits qu'ils souhaitent et l'orthographier dans le nom de la méthode est assez claire.


Assez juste. Merci pour vos suggestions!



1
votes

Je dirais la stratégie alternative, si vous voulez travailler avec des primitives, est de faire ce que font les bibliothèques Java. Il suffit de le sucer et d'avoir plusieurs méthodes.

Par exemple, ObjectInphatStretream a ReadDouble () Code>, Loadbyte () Code>, etc. P>

vous ' Ne gagnez rien en partageant une implémentation de la fonction, et les clients de votre fonction ne gagnent rien par les variantes de votre fonction ayant tous le même nom. P>

Mise à jour forte> P>

Considérant votre mise à jour, je ne pense pas qu'il soit nécessaire de faire dupliquer trop de code. Cela dépend de votre stratégie de codage, mais j'imagine que vous pouviez faire quelque chose comme ceci: p> xxx pré>

tout ce qui partage le code plus que cela est probablement sur-ingénierie. P> Une alternative pourrait être p> xxx pré>

IE Je ne pense pas qu'il est logique d'exposer les utilisateurs de votre bibliothèque à autre chose que les types primitifs eux-mêmes. P>

Si vous êtes vraiment, je voulais vraiment que vous puissiez faire une seule méthode d'accès à celui-ci: P>

@SuppressWarnings("unchecked")
public static <T> T getValue(Class<T> clazz) {
    if ( clazz == byte.class ) {
        return (T)Byte.valueOf((byte)getBits(8));
    } else if ( clazz == int.class ) {
        return (T)Integer.valueOf((int)getBits(32));
    }
    throw new UnsupportedOperationException(clazz.toString());
}

//...
byte b = getValue(byte.class);
int i = getValue(int.class);


1 commentaires

hahaha ... assez juste. Si je ne trouve pas une solution qui me rend heureux, j'irai avec les multiples méthodes.



0
votes

Oui, s'il vous plaît soyez plus précis sur ce que vous voulez réaliser. De votre description, je vous suggère de jeter un coup d'œil aux génériques Java où vous pourriez écrire quelque chose comme ceci:

class SomeClass <GenericType> {
  GenericType val;  

  void setValue(GenericType val) {
     this.val = val;
  }

  GenericType getValue() {
     return val;
  }

  public static void main(String[] args) {
    SomeClass<Integer> myObj = new SomeClass<Integer>();
    myObj.setValue(5);
    System.out.println(myObj.getValue());

    SomeClass<String> myObj2 = new SomeClass<String>();
    myObj2.setValue("hello?!");
    System.out.println(myObj2.getValue());

  }

}


1 commentaires

J'ai ajouté une mise à jour à mon post. Veuillez vous référer à cela pour plus d'informations.



1
votes

On dirait que vous avez un ensemble de bits que vous analysez. Vous devriez l'avoir enveloppé dans un objet, appelons cet objet un bitset. Vous êtes itération à travers les bits, vous aurez donc quelque chose comme un itérateur , et comme vous vous voulez faire analyser les octets, les intentes, les longs, etc ..., etc., alors vous aurez votre analyseur de classe, et il y a des méthodes sur celui-ci comme: xxx

etc ...

Donc, après avoir appelé la méthode dont vous avez besoin, vous avez Extrait de la valeur que vous souhaitez sous une manière TypeAfe (types de rendement différents pour différentes méthodes) et que l'itérateur a été déplacé vers l'avant le nombre correct de positions, en fonction du type.

est-ce ce que vous cherchez pour?


2 commentaires

En fait ... ce n'est pas une mauvaise idée ... mais j'utiliserai une intrigue. Néanmoins, c'est une suggestion intéressante. Merci.


Eh bien, si vous utilisez InputStream, alors c'est encore plus facile! Vous venez de le transmettre à vos différentes fonctions et de lire autant d'octets que nécessaire. Votre position dans le flux passe en avant chaque fois que vous appelez une fonction, par autant d'octets que nécessaire par cette fonction. C'est de la tarte!