Impossible de lancer java.lang.Flotter pour flotter lors de l'utilisation de la classe.casting?


J'ai déjà une solution, mais je ne l'aime pas. Aussi, il serait bon de connaître vos pensées à ce sujet.

Vous voyez, elem.get renvoie une Object, qui va être un Float dans le cas de x et y.

Ce code lève l'exception décrite dans le titre:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);
        arg.add(types[i].cast(elem.get(names[i])));
    }
}

Le code est utilisé pour définir la liste des paramètres pour instancier un objet. Les paramètres et le nom de classe de l'objet sont définis dans un fichier de données externe (mais peu importe que).

La solution, quelque chose que je n'aime pas (parce qu'elle perd la flexibilité que j'essayais d'atteindre), a ceci dans le for:

if(types[i] == float.class)
{
    float v = (Float)elem.get(names[i]);
    arg.add(v);
} else
{
    arg.add(types[i].cast(elem.get(names[i])));
    break;
}

Une autre option changerait float.class en Float.class dans types, mais je ne le ferai pas car ce code est utilisé pour instancier des objets qui ont des paramètres float dans leurs constructeurs.

Merci!

Author: jeha, 2011-09-23

1 answers

Comme le type de args est un ArrayList<Object>, vous n'évitez pas la boxe de toute façon:

// This code...
float v = (Float)elem.get(names[i]);
arg.add(v);

// Will actually be equivalent to:
float v = (Float)elem.get(names[i]);
Float boxed = v;
arg.add(boxed);

Si le but est d'appeler un constructeur par réflexion, alors vous allez avoir pour passer un Float pour tous les paramètres float - c'est comme ça que ça marche.

Donc fondamentalement, changez float.class en Float.class et tout devrait bien fonctionner. EDIT: Ah, sauf que la liste par aura le mauvais type. Fondamentalement, vous voulez cast avec Float.class, mais ajouter float.class pour la liste des les types de paramètre.

Vous voulez probablement une carte des types primitifs aux types wrapper, comme ceci:

private static final Map<Class<?>>, Class<?>> PRIMITIVE_TYPE_MAP =
    buildPrimitiveTypeMap();

private static Map<Class<?>>, Class<?>> buildPrimitiveTypeMap()
{
    Map<Class<?>>, Class<?>> map = new HashMap<Class<?>>, Class<?>>();
    map.put(float.class, Float.class);
    map.put(double.class, Double.class);
    // etc
    return map;
}

Puis:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);

        // For primitive types, only box to the wrapper type
        Class<?> castType = PRIMITIVE_TYPE_MAP.get(types[i]);
        if (castType == null)
        {
            castType = types[i];
        }
        arg.add(castType.cast(elem.get(names[i])));
    }
}

En fait, si vous croyez que les valeurs sont déjà du bon type, je soupçonne que vous pouvez simplement faire:

arg.add(elem.get(names[i]));

Après tout, vous passez simplement à un type particulier, puis vous perdez à nouveau ces informations de type... l'utilisation de l'appel cast vérifie cependant que les types d'exécution sont corrects, vous pouvez donc le conserver pour que la raison.

 2
Author: Jon Skeet, 2011-09-22 21:47:06