简体   繁体   中英

How to implement a generic method in java

I need to override this method:

   @Override
   public <T> T convertValue(Object object, Class<T> clazz) 

problem is I dont know why. I dont understand what is <T> . I try to rewrite it and replace T with String class:

   public <String> String convertValue(Object object, Class<String> clazz){
        return "a";
    }

but this give me error:

Type mismatch: cannot convert from java.lang.String to String

so now I am really confused. Can someone explain me this and show some example how to return some value ?

T is a type parameter. It's a "placeholder" for a type.

The error you're getting is because you're shadowing ("hiding") the String type with your String type parameter . You need to remove the type parameter for the types to resolve correctly.

Also, note that even then you'll not be able to override the method since this

    @Override
    public String convertValue(Object object, Class<String> clazz){
            return "a";
    }

has an incompatible type signature with A.convertValue() .

This is because, in simple terms, Java requires that you should be able to use the overriding implementation of B.convertValue() wherever you can use A.convertValue() without compile errors. So you should preserve the type parameter, as JB Nizet correctly suggests.

Finally, there's a strong suspicion you might not understand what the method convertValue is about. Again, read JB Nizet's answer, as he provides an intuitive explanation, and be sure to read up on basic generics .

public <T> T convertValue(Object object, Class<T> clazz) 

is a generic method. It accepts any object, and a Class instance clazz, and it's supposed to return an instance of the given class.

So, you can call it like this:

String s = foo.<String>convertValue(someObject, String.class);

or simply

String s = foo.convertValue(someObject, String.class);

thanks to type inference.

If you have to override it, then your method implementation must comply with the contract of the base method. You can only return a String if the clazz argument is String.class . An implementation that returns "a" always and throws an exception if the clazz is not String.class would be, for example:

@Override
public <T> T convertValue(Object object, Class<T> clazz) {
    if (clazz == String.class) {
        return (T) "a";
    }
    else {
        throw new IllegalArgumentException("I only support String, sorry");
    }
}

The rule for overriding The return type should be the same or a subtype of the return type declared in the original overridden method in the superclass .

So it is not possible to override generic method with non generic method in the sub class unless if you specifically declare type of T when you extends like below

class A <T> {
    public T method(T a){
        return a;
    }
}

class B extends A<String> {

    @Override
    public String tell(String a){
        return a;
    }
}

But this wont work for super class like below; where T is locally defined within the method level; and sub class don't have control over it. And Subclass will fail following the overriding rule.

class A  {
    public <T> T method(T a){
        return a;
    }
}  

Also read type erasure

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