Java generics: return bounded generic types

I follow this Code:

public <T extends ParentException> T managedException(Exception cause) {        
    if(ExceptionA.class.isinstance(cause)) {
        return ExceptionA.class.cast(cause);
    } else if(ExceptionB.class.isinstance(cause)) {
        return ExceptionB.class.cast(cause);
    } else if(ExceptionC.class.isinstance(cause)){
        return ExceptionC.class.cast(cause);
    } else {
        return new ExceptionD(cause.getMessage(),cause);
    }
}

Here, exceptiona, exceptionb, exceptionc and exceptiond are the children of parentexception

When compiling, I got an error:

incompatible types: ExceptionA cannot be converted to T
incompatible types: ExceptionB cannot be converted to T
incompatible types: ExceptionC cannot be converted to T
incompatible types: ExceptionD cannot be converted to T

However, if I change the code to:

@SuppressWarnings("unchecked")
public <T extends ParentException> T managedException(Exception cause) {        
    if(ExceptionA.class.isinstance(cause)) {
        return (T) ExceptionA.class.cast(cause);
    } else if(ExceptionB.class.isinstance(cause)) {
        return (T) ExceptionB.class.cast(cause);
    } else if(ExceptionC.class.isinstance(cause)){
        return (T) ExceptionC.class.cast(cause);
    } else {
        return (T) new ExceptionD(cause.getMessage(),cause);
    }
}

It has no compilation errors

As mentioned in the answer of so thread: @ L_ 301_ 0 @, it is allowed to use t for conversion, and give another pointer in this thread: Java genetics: generic type defined as return type only But my question is: when t is bounded and all returned objects fall, why do I need to use type conversion to enter the specified boundary?

Solution

What you are doing is wrong That's why you got wrong You can use exceptionc exceptionc = managedexception (exceptiond d) to call your method, and you will eventually get a cast (exceptionc) exception D; And it masks errors, but you get it at run time

Change your method to:

public ParentException managedException(Exception cause) {        
    if(ExceptionA.class.isinstance(cause)) {
        return ExceptionA.class.cast(cause);
    } else if(ExceptionB.class.isinstance(cause)) {
        return ExceptionB.class.cast(cause);
    } else if(ExceptionC.class.isinstance(cause)){
        return ExceptionC.class.cast(cause);
    } else {
        return new ExceptionD(cause.getMessage(),cause);
    }
}

You don't need generics here All these exceptions are also parentexceptions, so you can return them When you think about it, you try to get methods to return different types This is impossible because if you have a variable initialized from this method, you need to know what the result is And you know the result will be parentexception, but you can't know which parent exception

The reason behind it is that if your method is not written to return parentexception - it returns t (a subclass) And you can return different types of subclasses instead of the subclasses you want to get

In a simpler example, if we have:

class A {}

class B extends A{  };

class C extends A{  };

public  <T extends A> T test() {        
        return (T) new B();
}

We can call it with C = test(); We actually try to cast (c) new (b); This is incompatible, but we have masked it and we get exceptions at run time

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>