6

I'm converting people's data into condensed form. So I have a bunch of interfaces:

public interface Brief {}
public interface Detail {}

public interface DetailToBriefConverter<T extends Detail, R extends Brief>  {
    R convert(T detail);
}

, a bunch of pojos:

public class StudentBrief implements Brief {...}
public class StudentDetail implements Detail {...}
public class EmployeeBrief implements Brief {...}
public class EmployeeDetail implements Detail {...}

and converters:

public class StudentDetailToBriefConverter implements DetailToBriefConverter<StudentDetail, StudentBrief> {
@Override
public StudentBrief convert(StudentDetail detail) {
    // logic here
    }
}

etc.

My main class looks roughly like this:

public class MainApp {

private Map<String, DetailToBriefConverter> map = ImmutableMap.<String, DetailToBriefConverter>builder()
        .put("employee", new EmployeeDetailToBriefConverter())
        .put("student", new StudentDetailToBriefConverter())
        .build();

public static void main(String[] args) {
    MainApp mainApp = new MainApp();
    String type = "employee"; // comes from the request actually
    Detail detail = new EmployeeDetail(); // comes from the request
    DetailToBriefConverter detailToBriefConverter = mainApp.map.get(type);
    detailToBriefConverter.convert(detail);
    }
}

And this works, but I get a warning unchecked call to convert(T) as a member of a raw type DetailToBriefConverter.

How can I get rid of this warning or do I have to live with it?

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
J.Doe
  • 287
  • 1
  • 5
  • 16
  • To get rid of the warning, you can either [suppress it](https://stackoverflow.com/questions/1129795/what-is-suppresswarnings-unchecked-in-java) or use the generic version of `DetailToBriefConverter`. – Bhesh Gurung Aug 07 '18 at 21:27
  • The fact that the keys in the map are strings makes it impossible to do this in a way that's statically type-safe. The alternative to the raw type is to use unchecked casting, or to not make `DetailToBriefConverter` generic in the first place. – Radiodef Aug 07 '18 at 21:30

2 Answers2

6
DetailToBriefConverter detailToBriefConverter = mainApp.map.get(type);

detailToBriefConverter is a raw type: you aren't giving it a type parameter. Nor are you giving it one in the map.

Given that you are putting heterogeneous types into the map, the only type parameter you can use is <?, ?>:

DetailToBriefConverter<?, ?> detailToBriefConverter = mainApp.map.get(type);

(add it to the map declaration too)

But then you've got the problem that you can't invoke detail like this:

detailToBriefConverter.convert(detail);

because the type of the parameter is ?, and you've got an EmployeeDetail, or whatever it is called.

Basically, what you are trying to do isn't type safe. It is possible that you can write the code in such a way that you don't actually get any runtime exceptions; but it's rather brittle.


What you really need is a type-safe heterogeneous container. Look it up in Effective Java or elsewhere.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

Change your method declaration to

public interface DetailToBriefConverter<T extends Detail, R extends Brief>  {
    Brief convert(Detail  detail);
}

And where you have declared DetailToBriefConverter, declare it is as DetailToBriefConverter

public class MainApp {

private Map<String, DetailToBriefConverter<? extends Detail, ? extends Brief>> map = ImmutableMap.<String, DetailToBriefConverter<? extends Detail, ? extends Brief>>builder()
        .put("employee", new EmployeeDetailToBriefConverter())
        .put("student", new StudentDetailToBriefConverter())
        .build();

public static void main(String[] args) {
    MainApp mainApp = new MainApp();
    String type = "employee"; // comes from the request actually
    Detail detail = new EmployeeDetail(); // comes from the request
    DetailToBriefConverter<? extends Detail, ? extends Brief> detailToBriefConverter = mainApp.map.get(type);
    detailToBriefConverter.convert(detail);
    }
}

Basically when you declare the class, you need to specify the types, else you will get the raw types warning

user699848
  • 109
  • 7
  • 1
    If you're doing this, you may as well just remove the type parameters on `DetailToBriefConverter` altogether. – VeeArr Aug 07 '18 at 22:01
  • yeah, the whole idea was to have generic convert method, however it does remove the warning – J.Doe Aug 07 '18 at 22:07