Why does this program include a common interface method?

The following code throws ClassCastExceptionat runtime, and the line public String foo() { return "bar"; }generates a warning “found” java.lang.String ”, necessarily“ T. ”I understand ClassCastException(the interface method is called with T, equal Integer, but fooreturns a String), and I understand the warning (it tries to warn us about this problem). But I don’t understand why the program compiles at all. Why does the method returning Stringallow overriding the method returning T?

public class Main {

    interface MyInterface {

        <T> T foo();
    }

    static class MyClass implements MyInterface {

        @Override
        public String foo() { return "bar"; }
    }

    public static void main(String[] args) {
        int a = ((MyInterface) new MyClass()).<Integer>foo();
    }
}
+4
source share
4 answers

. Java :

mC, C, C mA, A, :

  • mC (§8.4.2) mA.
  • ...

:

M N , , ( ) (§8.4.4) N M, .

, MyInterface.foo , MyClass.foo .

m1 m2, :

  • m2 , m1,
  • m1 (§4.6) m2.

:

, , . , , , . , , .

, , , MyClass.foo foo(), MyInterface.foo.

. :

d1 R1 d2 R2, d1 (§8.4.5 ) d2, .

:

d1 R1 - d2 R2, :

  • ...

  • R1 , :

    • R1, d2 (§8.4.4), R2.

    • R1 R2 (§5.1.9).

    • d1 , d2 (§8.4.2), R1 = | R2 |.

R1 = String R2 = T. , String T. String T , .

:

, , , . , R1 - R2, ​​ R1 R2, (§8.4.8.3, §9.4.1) .

, , , , . , ClassCastExceptions , . , . ( ) .

+2

<T> T foo();, foo , . . :

interface MyInterface {
    <T> T foo();
}

class MyClass implements MyInterface {
    @Override
    public String foo() { return "bar"; }
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = new MyClass();
        //the result of foo will be String
        String bar = myInterface.foo();
        System.out.println(bar); //prints "bar"
        try {
            //the result of foo at compile time will be Integer
            Integer fail = myInterface.foo();
            System.out.println(fail); //won't be executed
        } catch (ClassCastException e) {
            //for test purposes only. Exceptions should be managed better
            System.out.println(e.getMessage()); //prints "java.lang.String cannot be cast to java.lang.Integer"
        }
    }
}

Object. , , .

, .

:

  • <T> /:

    interface MyInterface<T> {
        T foo();
    }
    
    class MyClass implements MyInterface<String> {
        @Override
        //can only return String here. Compiler can check this
        public String foo() { return "bar"; }
    }
    
  • Class<T> , , :

    interface MyInterface {
        <T> T foo(Class<T> clazz);
    }
    
    class MyClass implements MyInterface {
        @Override
        public <T> T foo(Class<T> clazz) {
            try {
                return clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace(System.out);
            } catch (IllegalAccessException e) {
                e.printStackTrace(System.out);
            }
            return null;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            MyInterface myInterface = new MyClass();
            //uncomment line below to see the compiler error
            //Integer bar = myInterface.foo(String.class);
    
            //line below compiles and runs with no problem
            String bar = myInterface.foo(String.class);
            System.out.println(bar);
        }
    }
    
+4

<T> T foo() Object foo(). - - (, T, T foo()), - , . , , , .

+2

- T Object . , String.

0

Source: https://habr.com/ru/post/1569464/


All Articles