ClassCastException se produit lors de la migration de Java7 vers Java8 ~ Génériques et surcharge ~


Auto-introduction

LT sur Nagoya Java User Group avril 2018!


Environnement d'exécution


table des matières

  1. Problèmes survenus
  2. Recherchez la cause
  3. Résultats de l'enquête

1. Problèmes survenus


Que se passe-t-il lorsque vous l'exécutez?

Main.java



public class Main {

	public static void main(String[] args) {
		String.valueOf(hoge());
	}

	static <E> E hoge() {
		return (E) "hoge";
	}

}

Java7 se termine normalement, Java8 provoque une exception ClassCastException

Console


Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to [C
	at jp.co.sample.Main.main(Main.java:13)

[C est un tableau de caractères https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.8


Quelle est cette source en premier lieu?


Problèmes avec cette source

Ne vous inquiétez pas de cette annonce.


2. Recherchez la cause


Vérifier avec Eclipse

Le compilateur est ECJ (Eclipse Java Compiler), qui est différent de JDK, mais le résultat est le même.

image


Dans Java 7, le paramètre de type hoge est ʻObject`

Java7


En Java8, le paramètre de type hoge est char []

Java8

char [] provient de String.valueOf.


String.valueOf est surchargé

Peut accepter des arguments de type tableau char ou de type objet

String.valueOfのオーバロード


Arrangement de situation


Confirmation de la méthode générique

MainGenericsMethod.java


public class MainGenericsMethod {

	public static void main(String[] args) {
		String.valueOf(fuga("fuga"));
	}

	/**Le paramètre de type est déterminé à partir de l'argument*/
	static <E> E fuga(E arg) {
		return (E) arg;
	}
}

image


Vérifier la surcharge

Le résultat de l'exécution en Java 8 en modifiant la combinaison de méthodes surchargées.

Le problème est une méthode surchargée qui accepte un type d'objet ou un type de tableau.

MainOverload.java


public class MainOverload {

	public static void main(String[] args) {
		overload(hoge());
	}

	static <E> E hoge() {
		return (E) "hoge";
	}

	static void overload(Object arg) {}
	static void overload(char[] arg) {} //Changer le type d'argument
}

image


3. Résultats de l'enquête


Résumé


[Supplément] Surcharge ambiguë

Quand j'appelle une méthode surchargée qui reçoit ʻint [] ʻouchar [], j'obtiens une erreur de compilation qui dit" La surcharge de méthode (Object) est de type MainOverload est ambiguë. "

        //Erreur de compilation
	static void overload(int[] arg) {}
	static void overload(char[] arg) {}

Articles pouvant être liés à ce problème

So, whereas before Java 8 the method argument site did not receive any inference, defaulting to Object, in Java 8 the most specific applicable type is inferred, in this case String.


[Supplément] J'ai essayé l'assemblage inversé avec javap -verbose de Java8

Classfile /C:/Users/yuji3/Desktop/java-test/java8/Main.class
  Last modified 2018/04/14; size 476 bytes
  MD5 checksum 409af5d1b1986da6e0c4cd431dc50b59
  Compiled from "Main.java"
public class Main
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #7.#20         // java/lang/Object."<init>":()V
   #2 = Methodref          #6.#21         // Main.hoge:()Ljava/lang/Object;
   #3 = Class              #22            // "[C"
   #4 = Methodref          #23.#24        // java/lang/String.valueOf:([C)Ljava/lang/String;
   #5 = String             #14            // hoge
   #6 = Class              #25            // Main
   #7 = Class              #26            // java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               main
  #13 = Utf8               ([Ljava/lang/String;)V
  #14 = Utf8               hoge
  #15 = Utf8               ()Ljava/lang/Object;
  #16 = Utf8               Signature
  #17 = Utf8               <E:Ljava/lang/Object;>()TE;
  #18 = Utf8               SourceFile
  #19 = Utf8               Main.java
  #20 = NameAndType        #8:#9          // "<init>":()V
  #21 = NameAndType        #14:#15        // hoge:()Ljava/lang/Object;
  #22 = Utf8               [C
  #23 = Class              #27            // java/lang/String
  #24 = NameAndType        #28:#29        // valueOf:([C)Ljava/lang/String;
  #25 = Utf8               Main
  #26 = Utf8               java/lang/Object
  #27 = Utf8               java/lang/String
  #28 = Utf8               valueOf
  #29 = Utf8               ([C)Ljava/lang/String;
{
  public Main();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: invokestatic  #2                  // Method hoge:()Ljava/lang/Object;
         3: checkcast     #3                  // class "[C"
         6: invokestatic  #4                  // Method java/lang/String.valueOf:([C)Ljava/lang/String;
         9: pop
        10: return
      LineNumberTable:
        line 4: 0
        line 5: 10

  static <E extends java.lang.Object> E hoge();
    descriptor: ()Ljava/lang/Object;
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #5                  // String hoge
         2: areturn
      LineNumberTable:
        line 8: 0
    Signature: #17                          // <E:Ljava/lang/Object;>()TE;
}
SourceFile: "Main.java"

[Supplément] J'ai essayé l'assemblage inversé avec javap -verbose de Java7

Classfile /C:/Users/yuji3/Desktop/java-test/java7/Main.class
  Last modified 2018/04/14; size 481 bytes
  MD5 checksum 72c2eee8d5b013579f81dc56f53458d0
  Compiled from "Main.java"
public class Main
  SourceFile: "Main.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER

Constant pool:
   #1 = Methodref          #6.#19         //  java/lang/Object."<init>":()V
   #2 = Methodref          #5.#20         //  Main.hoge:()Ljava/lang/Object;
   #3 = Methodref          #21.#22        //  java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   #4 = String             #13            //  hoge
   #5 = Class              #23            //  Main
   #6 = Class              #24            //  java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               hoge
  #14 = Utf8               ()Ljava/lang/Object;
  #15 = Utf8               Signature
  #16 = Utf8               <E:Ljava/lang/Object;>()TE;
  #17 = Utf8               SourceFile
  #18 = Utf8               Main.java
  #19 = NameAndType        #7:#8          //  "<init>":()V
  #20 = NameAndType        #13:#14        //  hoge:()Ljava/lang/Object;
  #21 = Class              #25            //  java/lang/String
  #22 = NameAndType        #26:#27        //  valueOf:(Ljava/lang/Object;)Ljava/lang/String;
  #23 = Utf8               Main
  #24 = Utf8               java/lang/Object
  #25 = Utf8               java/lang/String
  #26 = Utf8               valueOf
  #27 = Utf8               (Ljava/lang/Object;)Ljava/lang/String;
{
  public Main();
    flags: ACC_PUBLIC

    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return        
      LineNumberTable:
        line 2: 0

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=1, locals=1, args_size=1
         0: invokestatic  #2                  // Method hoge:()Ljava/lang/Object;
         3: invokestatic  #3                  // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
         6: pop           
         7: return        
      LineNumberTable:
        line 4: 0
        line 5: 7

  static <E extends java/lang/Object> E hoge();
    flags: ACC_STATIC

    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #4                  // String hoge
         2: areturn       
      LineNumberTable:
        line 8: 0
    Signature: #16                          // <E:Ljava/lang/Object;>()TE;
}

Recommended Posts

ClassCastException se produit lors de la migration de Java7 vers Java8 ~ Génériques et surcharge ~
Comment écrire et noter lors de la migration de VB vers JAVA
Précautions lors de la migration de VB6.0 vers JAVA
[Opensaml] NoClassDefFoundError se produit lors du passage de Tomcat à weblogic
Ce à quoi j'ai pensé lorsque j'ai commencé à migrer de Java vers Kotlin
Modifications lors de la migration de Spring Boot 1.5 vers Spring Boot 2.0
Modifications lors de la migration de Spring Boot 2.0 vers Spring Boot 2.2
Mettez à jour JAVA vers la dernière version vers 1.8.0_144 (lors du téléchargement à partir du Web et de la mise à jour)
[Java] Conseils et problèmes d'erreur lors de la conversion du double en grand décimal
Résumé des points qui m'inquiétaient lors de la migration de Java vers Kotlin
Changements de Java 8 à Java 11
Somme de Java_1 à 100
De Java à Ruby !!
[Java] Surcharge et remplacement
Convertir l'énumération Java et JSON vers et depuis Jackson
Migration de Cobol vers JAVA
[Java] Classe générique et méthode générique
Nouvelles fonctionnalités de Java7 à Java8
Connectez-vous de Java à PostgreSQL
De Java inefficace à Java efficace
Remarques sur le code de caractère lors de la migration de Windows vers Mac
[Java] Copie superficielle et copie complète lors de la conversion d'un tableau en liste
De Java naissant (3 ans) à Node.js (4 ans). Et l'impression de retourner à Java
[Java] Comment convertir du type String en type Path et obtenir le chemin
Introduction à Scala du point de vue Java (basique)
Java sera impliqué dès aujourd'hui
De Java à VB.NET - Écriture de notes de contraste
Java, constructeur de surcharge à partir du débutant
Java, interface pour partir du débutant
Remarques sur la migration de CircleCI 1.0 vers 2.0
[Java] Essayez de mettre en œuvre à l'aide de génériques
Java Generics (définit les classes et les méthodes)
La route de JavaScript à Java
[Java] Conversion d'un tableau à une liste
Que faire lorsqu'une exception javax.batch.operations.JobStartException se produit
[Ruby / Refactoring] Du traitement itératif Ruby tel que Java et C au traitement itératif de type Ruby
J'ai essayé de traduire la grammaire de R et Java [Mis à jour de temps en temps]
Java pour les débutants, les variables et les types
Que faire lorsqu'une exception javax.el.PropertyNotWritableException se produit
Convertir l'heure UTC Java en heure JST
Implémentation Java pour créer et résoudre des labyrinthes
[Java] Comment sortir et écrire des fichiers!
De l'installation d'Eclipse à l'exécution de Java (PHP)
[Rails] [Note] Quand ajouter = à <%%> et quand pas
Java: Comment envoyer des valeurs du servlet au servlet
Lors de l'appel de l'API avec java, javax.net.ssl.SSLHandshakeException se produit
[Java] Flux du code source à l'exécution
Introduction à la surveillance à partir de Java Touching Prometheus
[Introduction à Java] À propos des déclarations et des types de variables
Mémo pour la migration de Java vers Kotlin
Conversion de type du type java Big Decimal au type String
De Java à C et de C à Java dans Android Studio
[Explication facile à comprendre! ] Comment utiliser la surcharge Java
Dépannage lors de la montée de Mastodon de la v3.0.x à la v3.1.x
Résumé des bons points et des précautions lors de la conversion de l'application Java Android vers Kotlin
[Promotion de la compréhension de Ruby (1)] Lorsque vous passez de Java à Ruby, commencez par comprendre la différence.
[Java] Exemple de programme qui acquiert les valeurs maximum et minimum d'un tableau
Résumé en essayant d'utiliser Solr en Java et en obtenant une erreur (Solr 6.x)