Tapez la sécurité avec des génériques en Java
J'ai rencontré un comportement de génériques en Java que j'ai complètement ne peut pas comprendre (avec mon .NET l'arrière-plan).
public class TestGeneric<T>
{
public void get (Object arg)
{
T temp = (T) arg;
System.out.println(temp.toString());
return;
}
}
TestGeneric<Integer> tg = new TestGeneric<Integer>();
tg.get("Crack!!!");
S'il vous plaît dites-moi pourquoi je ne reçois pas ClassCastException en obtenir, en outre, dans l'Idée, je vois temp que String
après la cession et de la valeur de "Crack!!!"
. Aussi, comment ai-je pu que ClassCastException avaient envoyé? Je suis à l'aide du JDK 1.7.0_07 sur Windows 7 x64.
source d'informationauteur starteleport
Vous devez vous connecter pour publier un commentaire.
La raison pour laquelle vous n'obtenez pas une classe cast exception est que Java génériques sont mis en œuvre par type d'effacement. À la différence .NET génériques qui ont nécessité d'importants changements à CLS, Java génériques sont traitées dans le moment de la compilation. Au moment de l'exécution, de la fonte à
T
est ignoré. Afin de vérifier le type à l'exécution, vous avez besoin de stockerClass<T>
et d'utiliser ses méthodes pour vérifier le type d'un paramètre passé dans l':C'est parce que le type générique T n'a pas de limites définies de sorte qu'il est traité comme un Objet. Quelque chose de Casting pour T ne sera pas provoquer un
ClassCastException
dans ce cas.Toutefois, si votre définition de la classe a été
public class TestGeneric<T extends Number>
puis vous obtenez le ClassCastException si vous avez passé dans une Chaîne de caractères en get().C'est un exercice instructif de réfléchir à ce que la non-génériques de code que le code générique est "effacée" ressemble:
Cela est dû à
type-erasure
. Cela signifie qu'en Java tous les génériques sont réduits àObject
au moment de l'exécution. Si vous avez joué votreString
àObject
qui est tout à fait bien. Et depuistoString
est mis en œuvre surObject
encore une fois, aucune exception.Voici un lien sur type-erasure
La seule façon de vraiment obtenir le
ClassCastException
est de passer une instance deClass<T>
pour le type générique et ensuite fairemyClass.isInstance(arg)
et de lever une exception sifalse
Rappelez-vous toujours les médicaments Génériques en Java sont la compilation des entités. Il n'a rien à faire au moment de l'exécution. Permettez-moi de démo de votre oqn code pour vous.
et la sortie est
De sens maintenant? Objet est la suprême super classe. Il peut donc être un objet String en raison de polymorphisme. Si vous êtes le type coulée ou plutôt je dirais de faire un nombre entier de point de référence à un objet de type string Java savoir en interne c'est une Chaîne de caractères de l'objet au moment de l'exécution. Il y aurait un problème si toString() n'était pas défini dans la classe Integer. La fonction que vous appelez doit être défini dans la référence, mais la mise en œuvre sera choisi de façon appropriée à la runtime de la objet référencé.
Si vous faites de cette façon, vous n'avez même pas besoin de vérifier la ClassCastException et il ne pourra même pas à compiler.
Le type
Integer
a une méthodetoString
. En fait, chaqueObject
a cette méthode de manièreClassCastException
ne se produira pas.Vous n'avez pas appeler tout
String
méthode spécifique sur votre objet est donc pas une exception s'est produite.La raison pour cela est que lors de l'exécution, vous ne verrez pas les paramètres de type beause de type d'effacement.
Le point est que, après que votre code est compilé, vous n'êtes plus en mesure de voir les paramètres de type générique parce qu'ils sont effacées.
Il est une autre question ici, ce qui explique la classe cast exception: explication
Dans ce code, vous pouvez voir que l'utilisateur a essayé de semer explicitement à
String
pas à un paramètre générique.De sorte que vous pouvez appeler cela un défaut de java par rapport à C#.