120 votes

Java Class.cast () vs opérateur de distribution

Après avoir enseigné pendant mon C++ jours sur les maux de la C-style opérateur de cast, j'ai été heureux d'abord de trouver que dans Java 5 java.lang.Class avaient acquis une cast méthode.

J'ai pensé que nous avons enfin un OO façon de traiter avec la coulée.

S'avère Class.cast n'est pas le même que static_cast en C++. C'est plus comme reinterpret_cast. Il ne générera pas d'erreur de compilation où il est prévu et au lieu de s'en remettent à l'exécution. Voici un test simple de cas pour illustrer les différents comportements.

package test;

import static org.junit.Assert.assertTrue;

import org.junit.Test;


public class TestCast
{
    static final class Foo
    {
    }

    static class Bar
    {
    }

    static final class BarSubclass
        extends Bar
    {
    }

    @Test
    public void test ( )
    {
        final Foo foo = new Foo( );
        final Bar bar = new Bar( );
        final BarSubclass bar_subclass = new BarSubclass( );

        {
            final Bar bar_ref = bar;
        }

        {
            // Compilation error
            final Bar bar_ref = foo;
        }
        {
            // Compilation error
            final Bar bar_ref = (Bar) foo;
        }

        try
        {
            // !!! Compiles fine, runtime exception
            Bar.class.cast( foo );
        }
        catch ( final ClassCastException ex )
        {
            assertTrue( true );
        }

        {
            final Bar bar_ref = bar_subclass;
        }

        try
        {
            // Compiles fine, runtime exception, equivalent of C++ dynamic_cast
            final BarSubclass bar_subclass_ref = (BarSubclass) bar;
        }
        catch ( final ClassCastException ex )
        {
            assertTrue( true );
        }
    }
}

Donc, voici mes questions.

  1. Devrait - Class.cast() être banni à des Génériques de terre? Là, il a fait quelques utilisations légitimes.
  2. Devrait compilateurs génèrent des erreurs de compilation lors de l' Class.cast() est utilisé et les conditions de travail illégales peuvent être déterminés au moment de la compilation?
  3. Devrait Java fournir un opérateur de cast comme une construction du langage similaire à C++?

136voto

sfussenegger Points 16204

Je n'ai jamais utilisé de Classe.cast(Objet) pour éviter les mises en garde dans la "génériques". Je vois souvent des méthodes de faire des choses comme cela:

@SuppressWarnings("unchecked")
<T> T doSomething() {
    Object o;
    // snip
    return (T) o;
}

Il est souvent préférable de le remplacer par

<T> T doSomething(Class<T> cls) {
    Object o;
    // snip
    return cls.cast(o);
}

C'est le seul cas d'utilisation pour la Classe.cast(Objet) que j'ai jamais rencontré.

Concernant les avertissements du compilateur: je soupçonne la Classe.cast(Objet) n'est pas spécial pour le compilateur. Il pourrait être optimisée lorsque utilisé de manière statique (c'est à dire Foo.classe.casting(s) plutôt que de cls.cast(o)) mais je n'ai jamais vu quelqu'un l'utiliser - ce qui en fait l'effort de construction de cette optimisation dans le compilateur un peu inutile.

23voto

notnoop Points 30218

Tout d'abord, il vous est fortement déconseillé de faire presque n'importe quelle distribution, de sorte que vous devriez limiter autant que possible! Vous perdez les avantages de Java au moment de la compilation fortement typées fonctionnalités.

En tout cas, Class.cast() doit être utilisé principalement lors de l'extraction de l' Class jeton via la réflexion. C'est plus idiomatique écrire

MyObject myObject = (MyObject) object

plutôt que de

MyObject myObject = MyObject.class.cast(object)

EDIT: Erreurs lors de la compilation

Dans l'ensemble, Java effectue fonte des contrôles au moment de l'exécution. Cependant, le compilateur peut émettre une erreur si l'on peut prouver que les moulages peuvent jamais réussir (par exemple, fonte d'une classe à une autre classe qui n'est pas un supertype et jette un dernier type de classe à la classe/de l'interface qui n'est pas son type de hiérarchie). Ici depuis Foo et Bar sont des classes qui ne sont pas les uns les autres de la hiérarchie, le casting ne pourra jamais réussir.

17voto

cletus Points 276888

Il est toujours difficile et souvent trompeuse de traduire des constructions et des concepts entre les langues. Casting ne fait pas exception. En particulier parce que Java est un langage dynamique et C++ est quelque peu différente.

Tous les casting en Java, peu importe comment vous le faites, se fait au moment de l'exécution. Type d'information est organisée au moment de l'exécution. C++ est un peu plus de un mélange. Vous pouvez lancer une struct en C++ à l'autre, et c'est simplement une réinterprétation des octets qui représentent ces structures. Java ne fonctionne pas de cette façon.

Aussi les génériques en Java et C++ sont très différents. N'avez pas à vous soucier trop de comment faire du C++ choses en Java. Vous avez besoin d'apprendre comment faire les choses en Java.

14voto

Joachim Sauer Points 133411

Class.cast() est rarement utilisé dans du code Java. Si elle est utilisée généralement avec des types qui ne sont connus qu'au moment de l'exécution (c'est à dire par l'intermédiaire de leurs respectifs Class objets et par un certain type de paramètre). Il est vraiment plus utile dans le code qui utilise les génériques (qui est aussi la raison pour laquelle il n'était pas présenté plus tôt).

C'est pas semblable à l' reinterpret_cast, car elle ne sera pas vous permettre de briser le système de type à l'exécution, pas plus que la normale en fonte (c'est à dire que vous pouvez "pause" paramètres de type générique, mais ne peut pas "casser" les "vrais" types).

Les maux de la C-style opérateur de cast en général ne s'appliquent pas à Java. Le code Java qui ressemble à un style C cast est plus semblable à une dynamic_cast<>() avec un type de référence en Java (rappelez-vous: en Java runtime type d'information).

Généralement comparant le C++ casting opérateurs avec Java casting est assez difficile car en Java, vous ne pouvez jamais jeté de référence et aucune conversion n'arrive jamais à des objets (uniquement des valeurs primitives peuvent être convertis en utilisant cette syntaxe).

3voto

Mark Points 21191

C ++ et Java sont des langages différents.

L'opérateur de conversion de style C Java est beaucoup plus restreint que la version C / C ++. En réalité, la distribution Java est semblable à la diffusion dynamique C ++ C ++. Si l'objet que vous possédez ne peut pas être converti dans la nouvelle classe, vous obtiendrez une exception d'exécution (ou, si le code contient suffisamment d'informations, une exception de compilation). Ainsi, l'idée en C ++ de ne pas utiliser les transtypages de type C n'est pas une bonne idée en Java

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X