1

Java6 から Java8 に切り替えた後、問題に直面しています。

突然

java.lang.ClassCastException: java.base/java.lang.Integer は java.base/[Ljava.lang.Object; にキャストできません。

投げられます。

java.lang.reflect.Method.invoke(Object obj, Object... args) の varargs 引数にジェネリック型がマッチしていないようです。

コードがクリーンにコンパイルされ、実行時にのみ失敗するという事実により、これは私にとって非常に恐ろしいように見えます。ちなみに、java8でもソース/ターゲット定義が1.8以下ならコンパイル、実行成功!

理解を深めるために、小さな JUnit の例を用意しました。

public class GenericVarArgTest {
private static InnerClass myInnerClass;

@Test
public void testMethodInvocation()
        throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    doSomething();

    System.out.println("Done .. all fine");
}

private void doSomething() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    myInnerClass = this.new InnerClass();
    Method[] methods = myInnerClass.getClass().getMethods();
    for (Method aktMethod : methods) {
        if (aktMethod.getName().equals("printInteger")) {

            // this will always be okay
            // Integer myParam = getSomething();
            // aktMethod.invoke(myInnerClass, myParam);

            // this is just ok, for source / target level <= 1.7 
            aktMethod.invoke(myInnerClass, getSomething());
        }
    }
}

public static <T> T getSomething() {

    final T result = (T) Integer.valueOf(1);

    System.out.println("getSomething will return <T> : " + result);
    return result;
}

public class InnerClass {

    public String printInteger(final Integer aInteger) {
        final String result = "Integer: " + aInteger;
        System.out.println("Will return : " + result);
        return result;
    }
}

このpomを使用して、mavenでこの小さなテストをセットアップしました:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.test.java</groupId>
<artifactId>compiler-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>compiler test</name>
<description>Test the different compiler results    </description>

<properties>
    <java.version>1.8</java.version>

    <project.java.source.level>${java.version}</project.java.source.level>
    <project.java.target.level>${java.version}</project.java.target.level>
</properties>


<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
                <source>${project.java.source.level}</source>
                <target>${project.java.target.level}</target>
            </configuration>
        </plugin>
    </plugins>
</build>


<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

このpomを実行すると

mvn clean compile test -Djava.version= 1.6

すべて順調。しかし、それを実行する

mvn clean compile test -Djava.version= 1.8

ClassCastException が発生します。

この動作が変更された理由のヒント。これはバグですか (または 1.8 までバグでしたか)? 説明をありがとう。

4

1 に答える 1