ClassCastException tritt bei der Migration von Java7 auf Java8 auf. ~ Generics and overload ~


Vorstellen

LT bei Nagoya Java User Group April 2018!


Ausführungsumgebung


Inhaltsverzeichnis

  1. Probleme, die aufgetreten sind
  2. Untersuchen Sie die Ursache
  3. Ergebnisse der Untersuchung

1. Probleme, die aufgetreten sind


Was passiert, wenn Sie es ausführen?

Main.java



public class Main {

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

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

}

Java7 endet normal, Java8 verursacht 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 ist ein char-Array https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.8


Was ist diese Quelle überhaupt?


Probleme mit dieser Quelle

Mach dir keine Sorgen über diese Ankündigung.


2. Untersuchen Sie die Ursache


Fragen Sie bei Eclipse nach

Der Compiler ist ECJ (Eclipse Java Compiler), der sich von JDK unterscheidet, aber das Ergebnis ist das gleiche.

image


In Java 7 lautet der Parameter hoge type "Object"

Java7


In Java8 lautet der Parameter für den Hoge-Typ "char []"

Java8

char [] kommt von String.valueOf.


String.valueOf ist überladen

Kann Argumente vom Typ char array type oder Object type akzeptieren

String.valueOfのオーバロード


Situationsanordnung


Bestätigung der generischen Methode

MainGenericsMethod.java


public class MainGenericsMethod {

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

	/**Der Typparameter wird aus dem Argument bestimmt*/
	static <E> E fuga(E arg) {
		return (E) arg;
	}
}

image


Auf Überlastung prüfen

Das Ergebnis der Ausführung in Java 8 durch Ändern der Kombination überladener Methoden.

Das Problem ist eine überladene Methode, die einen Objekttyp oder einen Array-Typ akzeptiert.

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) {} //Argumenttyp ändern
}

image


3. Ergebnisse der Untersuchung


Zusammenfassung


[Ergänzung] Mehrdeutige Überlastung

Das Aufrufen einer überladenen Methode, die "int []" oder "char []" empfängt, führt zu einem Kompilierungsfehler, der besagt, dass "Methodenüberladung (Objekt) vom Typ MainOverload ist mehrdeutig".

        //Kompilierungsfehler
	static void overload(int[] arg) {}
	static void overload(char[] arg) {}

Artikel, die sich möglicherweise auf dieses Problem beziehen

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.


[Ergänzung] Ich habe versucht, mit javap -verbose von Java8 umzukehren

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"

[Ergänzung] Ich habe versucht, mit javap -verbose von Java7 Reverse Assembling durchzuführen

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 tritt bei der Migration von Java7 auf Java8 auf. ~ Generics and overload ~
Schreiben und Notizen bei der Migration von VB zu JAVA
Vorsichtsmaßnahmen bei der Migration von VB6.0 auf JAVA
[Opensaml] NoClassDefFoundError tritt auf, wenn von Tomcat zu Weblogic gewechselt wird
Woran ich dachte, als ich anfing, von Java nach Kotlin zu migrieren
Änderungen bei der Migration von Spring Boot 1.5 auf Spring Boot 2.0
Änderungen bei der Migration von Spring Boot 2.0 zu Spring Boot 2.2
Aktualisieren Sie JAVA auf die neueste Version auf 1.8.0_144 (beim Herunterladen aus dem Internet und Aktualisieren)
[Java] Tipps und Fehlerprobleme beim Konvertieren von Double zu Big Decimal
Zusammenfassung der Punkte, über die ich mir bei der Migration von Java nach Kotlin Sorgen gemacht habe
Änderungen von Java 8 zu Java 11
Summe von Java_1 bis 100
Von Java zu Ruby !!
[Java] Überladen und überschreiben
Konvertieren Sie Java Enum Enumeration und JSON von und nach Jackson
Migration von Cobol nach JAVA
[Java] Generics-Klasse und Generics-Methode
Neue Funktionen von Java7 bis Java8
Stellen Sie eine Verbindung von Java zu PostgreSQL her
Von ineffektivem Java zu effektivem Java
Hinweise zum Zeichencode bei der Migration von Windows auf Mac
[Java] Flache Kopie und tiefe Kopie beim Konvertieren eines Arrays in eine Liste
Vom jungen Java (3 Jahre) bis zu Node.js (4 Jahre). Und der Eindruck, nach Java zurückzukehren
[Java] So konvertieren Sie vom Typ String in den Pfadtyp und erhalten den Pfad
Einführung in Scala aus Java-Perspektive (grundlegend)
Java soll ab heute dabei sein
Von Java zu VB.NET-Writing Kontrastmemo-
Java, Überlastungskonstruktor ab Anfänger
Java, Schnittstelle für Anfänger
Hinweise zur Migration von CircleCI 1.0 auf 2.0
[Java] Versuchen Sie, mithilfe von Generika zu implementieren
Java Generics (definiert Klassen und Methoden)
Der Weg von JavaScript nach Java
[Java] Konvertierung von Array zu Liste
Was tun, wenn eine javax.batch.operations.JobStartException auftritt?
[Ruby / Refactoring] Von der iterativen Ruby-Verarbeitung wie Java und C bis zur Ruby-ähnlichen iterativen Verarbeitung
Ich habe versucht, die Grammatik von R und Java zu übersetzen [Von Zeit zu Zeit aktualisiert]
Java für Anfänger, Variablen und Typen
Was tun, wenn eine javax.el.PropertyNotWritableException auftritt?
Konvertieren Sie von der Java-UTC-Zeit in die JST-Zeit
Java-Implementierung zum Erstellen und Lösen von Labyrinthen
[Java] Wie man Dateien ausgibt und schreibt!
Von der Installation von Eclipse bis zur Ausführung von Java (PHP)
[Rails] [Hinweis] Wann = zu <%%> hinzugefügt werden soll und wann nicht
Java: So senden Sie Werte von Servlet zu Servlet
Beim Aufrufen der API mit Java tritt eine javax.net.ssl.SSLHandshakeException auf
[Java] Fluss vom Quellcode zur Ausführung
Einführung in die Überwachung von Java Touching Prometheus
[Einführung in Java] Informationen zu Variablendeklarationen und -typen
Memo für die Migration von Java nach Kotlin
Typkonvertierung vom Java Big Decimal-Typ zum String-Typ
Von Java nach C und von C nach Java in Android Studio
[Leicht verständliche Erklärung! ] Verwendung von Java-Überladung
Fehlerbehebung beim Anheben von Mastodon von v3.0.x auf v3.1.x.
Zusammenfassung der guten Punkte und Vorsichtsmaßnahmen bei der Konvertierung der Java Android-Anwendung in Kotlin
[Förderung des Ruby-Verständnisses (1)] Wenn Sie von Java zu Ruby wechseln, verstehen Sie zuerst den Unterschied.
[Java] Beispiel eines Programms, das die Maximal- und Minimalwerte von einem Array abruft
Zusammenfassung beim Versuch, Solr in Java zu verwenden und eine Fehlermeldung zu erhalten (Solr 6.x)