3

I have a method that works, but give me a warning, is there any solution to remove it, cleanly?

  • In this method I call the method :
    <T extends SonarContainPaging> T getSonarObjectFromPage(String url, Map<String, Object> uriVariables, Class<T> klass, List<T> page)
    That return an object that extends SonarContainPaging.

  • I try to add an object that extends SonarContainPaging to my list, but I get a warning.

  • The SonarContainPaging object has a method canContinuePaging that takes a page integer and return a boolean.


The warning:

Type safety: Unchecked cast from SonarContainPaging to T

private <T extends SonarContainPaging> void getSonarListContainingPaging(String url, Map<String, Object> uriVariables, 
        Class<T> klass, List<T> list) {
    int page = 1;
    SonarContainPaging sonarObject = getSonarObjectFromPage(url, uriVariables, klass, page);
    page++;

    list.add((T)sonarObject); // Warning
    while (sonarObject.canContinueLooping(page)) {
        sonarObject = getSonarObjectFromPage(url, uriVariables, klass, page);
        page++;

        list.add((T) sonarObject); // Warning
    }
}

Any solution you can think of?


The solution given by @Sweeper is to change the type of sonarObject to T
The error I made, was assuming that a generic T object could not call method from its parent.

Hamza Ince
  • 604
  • 17
  • 46
  • 2
    Dirty method: Annotate the method with: @SupressWarnings("unchecked"). Clean method: Check instanceOf before casting. – Manoj Vadehra May 28 '19 at 08:38
  • 2
    Possible duplicate of [Cast to generic type (T) gives "unchecked cast" warning](https://stackoverflow.com/questions/19032215/cast-to-generic-type-t-gives-unchecked-cast-warning) – Matthew May 28 '19 at 08:39
  • @Eran, hi Eran the signature is the question. ` T getSonarObjectFromPage(String url, Map uriVariables, Class klass, List page) ` – Hamza Ince May 28 '19 at 08:40

4 Answers4

3

The solution is to use T as the type here and then you can remove your casts:

// before:
// SonarContainPaging sonarObject = getSonarObjectFromPage(url, uriVariables, klass, page);
// after:
T sonarObject = getSonarObjectFromPage(url, uriVariables, klass, page);

Since according to your comment, getSonarObjectFromPage returns T, where T is the class you pass it in:

<T extends SonarContainPaging> T getSonarObjectFromPage(String url, Map<String, Object> uriVariables, Class<T> klass, List<T> page)

In this case you passed the class klass, which is a Class<T>, so getSonarObjectFromPage will return a T as well.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Yes, but I also need to call the method `canContinueLooping`, in the class SonarContainPaging. Still, I don't get why there is a cast warning, since I declared that `` in the method signature. And for that I need to cast the T object to a SonarContainPaging. – Hamza Ince May 28 '19 at 08:44
  • @HamzaInce Does my answer not work? What error does it produce? The warning occurs because `T` could be any subclass of `SonarContainPaging`. Let's say there is a subclass called `Foo`. You certainly can't cast an instance of `SonarContainPaging` into a `Foo`, can you? – Sweeper May 28 '19 at 08:47
  • I didn't expect it to work because I need to call a method in the SonarContainPagging object, but I previously declared that `T extends SonarContainPaging`. I leaned Java better today. thank you – Hamza Ince May 28 '19 at 08:51
1

There are two ways in general to avoid this warning.

The first is to cast the object to the class:

public static <T> T castMe(Class<T> clazz, Object object) {

    return clazz.cast(object);
}

The second one is to suppress the warning with an annotation. It's a bit of an unsure way about it but can safely be used when you absolutely know that that specific object can be cast to the generic type in question:

@SuppressWarnings("unchecked")
public static <T> T castMe(Class<T> clazz, Object object) {

    return (T) object;
}
Matthew
  • 1,905
  • 3
  • 19
  • 26
1

As mentioned by Sweeper already in their answer, you can just change the type of sonarObject to T:

T sonarObject;

You can also improve your code by using a do-while loop which reduces the redundancy you have:

private <T extends SonarContainPaging> void getSonarListContainingPaging(String url, Map<String, Object> uriVariables, Class<T> klass, List<T> list) {
    int page = 1;
    T sonarObject;
    do {
        sonarObject = getSonarObjectFromPage(url, uriVariables, klass, page);
        list.add(sonarObject);
    } while (sonarObject.canContinueLooping(++page));
}
Lino
  • 19,604
  • 6
  • 47
  • 65
1

You can use cast method. https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#cast-java.lang.Object-

list.add(klass.cast(sonarObject));

user
  • 31
  • 5