简体   繁体   中英

Java parametric signature resolution

Why does this code print 2.0 and not 1.0?

abstract class B<T extends Number> {
    abstract Number f(T j);
}

class A<T extends Number> extends B<T> {
    public Number f(Float j) {
        return 1f;
    }

    public Number f(T j) {
        return j;
    }
}

public class J {
    public static void main(String[] args) {
        B<Float> a = new A<>();
        Number r = a.f(2f);
        System.out.println(r);
    }
}

What are you expecting. You have only one method declared in class B:

abstract Number f(T j);

The method in the class A

public Number f(Float j);

does not override the former. They have different signatures. So the method

public Number f(T j) {
    return j;
}

gets called.

So the heart of the problem here is that you have declared the variable a to be of type B . Since the B class has only one method, that's the one that wins. However, in your main , if you change the type of a to be of type A , you'll notice that it will not compile because it is ambiguous. However, if you did change the method in the class A to accept a primitive instead, and in the main() method defined the variable a to be of type A , it would result in 1.0 . Ie, the following will result in printing 1.0 :

class A<T extends Number> extends B<T> {
    public Number f(float j) {
        return 1f;
    }

    public Number f(T j) {
        return j;
    }
}


public class J {
    public static void main(String[] args) {
        A<Float> a = new A<>();
        Number r = a.f(2f);
        System.out.println(r);
    }
}

In Your code below

abstract class B<T extends Number> {
 abstract Number f(T j);
}

class A<T extends Number> extends B<T> {
    public Number f(Float j) //this method does not override the superclass method

    {
        return 1f;
    }

    public Number f(T j) {
        return j;
    }
}

public class J {
    public static void main(String[] args) {
        B<Float> a = new A<>();
        Number r = a.f(2f);
        System.out.println(r);
    }
}

when call to af(2f) is occured it will call the

public Number f(T j)
{
return j;
}

which return j thus output provided is 2.0

float is not the same thing as Float .

Auto-boxing makes it feel the same, but one main difference is you can't pass a null into a float parameter.

I recommend using the @Override annotation on your overridden methods, so the compiler will tell you if the signature is correct

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM