0

I'm clearing out the warnings in Eclipse for

 ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized

but I don't understand why Eclipse uses the wildcard <?> periodically. Most of the time it puts in the correct type, i.e. ArrayList<Bicycle>. But with the following code if I do the List quickfix on Line 1 it changes to List<?> while if I do the quickfix on ArrayList first it changes to ArrayList<Object> even though the at Line 2 the method calls Line 3 and returns List<String>.

public List getList() {
    List treq = new ArrayList();
    List deptList = new ArrayList();  // Line 1
    try {
        treq = trDao.getList(status, dept, type, site);
        deptList = trDao.getDepts();  // Line 2
    }   
    catch (DAOException e) {
        setError(FORM_RESULTS, e.getMessage());
    }
    request.setAttribute("form", this);
    request.setAttribute("deptList", deptList);
    return treq;
}

and

public List<String> getDepts() {      // Line 3

Here is code which quickfixes trList as expected to ArrayList<RequestStudent> trList; The main difference I see is the use of .add()

public  ArrayList getListByRequestID(String request_id) throws DAOException {
    ArrayList trList;
    Connection connection = null;

    PreparedStatement ps = null;
    ResultSet rs = null;
    String SQL_GET_LIST = SELECT_QUERY + "WHERE trs.REQUEST_ID = ? " + "ORDER BY trs.STUDENT, trs.COURSE_ID";

    try {
        connection = ds.getConnection();
        ps = connection.prepareStatement(SQL_GET_LIST);
        ps.setString(1, request_id);
        rs = ps.executeQuery();
        trList = new ArrayList();

        while (rs.next()) {
            trList.add(mapResults(rs));  //mapResults returns a RequestStudent
        }
    }


    return trList;
}
jeff
  • 3,618
  • 9
  • 48
  • 101

2 Answers2

1

Eclipse can't guess what you actually want to return from the method. Such a method, for example, is perfectly valid:

public List<?> getList(int random) {
    if (random > 10) {
        return new ArrayList<String>();
    }
    else {
        return new ArrayList<Integer>();
    }
}

So, just because

deptList = trDao.getDepts();

assigns a List<String> to deptList doesn't mean that you don't want your deptList to be a List<?>, or a List<? extends Serializable>, or a List<? extends CharSequence> or any other type compatible with List<String>.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I'll have to digest your response because I have other similar cases where Eclipse puts in what I am returning from the method. So you are saying even though my method signature listed in Line CC above returns a List of Strings, Eclipse can't guess what I want returned? Line CC above is not as in your example "public List>" but "public List – jeff Sep 03 '15 at 20:54
  • My point is that this is valid: `List> getList() { return getDepts(); }`. Just like `Object foo() { return "hello"; }`. – JB Nizet Sep 03 '15 at 20:59
  • yes, OK, I agree with that but I am talking about the quickfix on Line AA. I never showed that the variable in Line AA was the list returned by the public List getList method. In fact it is not the list return. – jeff Sep 03 '15 at 21:22
  • The `deptList` variable you declare and initialize on line AA is then reassigned with the result of `getDepts()` in line BB, which is of type List. So it MUST be compatible with List. So it can be List, but also List>, or List extends CharSequence>, etc. – JB Nizet Sep 03 '15 at 21:26
1

Your getList() method is defined to return a raw List. Looking at the method itself, it's impossible to determine what generic type it should be returning, so Eclipse will recommend <?> or <Object> where it can (generally <?> for parameters and instances and <Object> for assignments and return types, but don't hold me to that).

new ArrayList() is equivalent to new ArrayList<Object>(), while List deptList = ... is dependant on the type it's being assigned to. Since the ArrayList is raw, Eclipse can't know what type it's supposed to be, and so goes with <?>.

You need to clean up your code to be explicit about what types you're working with. Never refer to a type with generics without specifying the generic type.

Assuming you're trying to work with Strings, your getList() should be:

public List<String> getList() {                          // add <String>
    List<String> treq = new ArrayList<>();               // add <String> and <>
    List<String> deptList = new ArrayList<>();           // add <String> and <>
    try {
        treq = trDao.getList(status, dept, type, site);
        deptList = trDao.getDepts();
    }   
    catch (DAOException e) {
        setError(FORM_RESULTS, e.getMessage());
    }
    request.setAttribute("form", this);
    request.setAttribute("deptList", deptList);
    return treq;
}

The difference in getListByRequestID() is that there is exactly one type being inserted into the List, so Eclipse can guess that you're intending to create a List of that type. In getList() there is no way to be sure what types might be inserted into treq and deptList, and so it has to fall back to <Object> or <?>.

Remember that Eclipse's suggestions are just that, suggestions. They may very well be wrong. You should only ever do them if you understand what they're doing, and are simply trying to avoid typing out boilerplate you already were planning to write.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • Ok I am starting to understand part of what is happening. It's probably poor coding but the list in Line AA is not the list being returned. If I add to the getList() method as you did above then, cool, I see that Eclipse quickfix properly, as expected adds to the local variable. But what is going on with the other local variable which is not returned in the getList() method? Again probably poor coding, but this is a refactor of some legacy code. – jeff Sep 03 '15 at 21:27
  • It's *definitely* poor coding. Raw types are, with few exceptions, a [very serious anti-pattern](http://stackoverflow.com/q/2770321/113632). I'm not sure what variable you're referring to by "the other local variable" seeing as you only define one variable, but in short Eclipse can only do so much. If you hand it very poorly structured code, it has little to go on. You need to intentionally fix your code to be correct, not just click quick-fixes until the warnings go away. – dimo414 Sep 03 '15 at 21:34
  • I posted more complete code. It's very old code, don't laugh.. I'm refactoring old JSP into JSF and just trying to go a step at a time: import old methods into JSF project, get things to compile, probably will blow a lot away. I'm not trying to use Raw (I think this means no ) which is why I was using Eclipse quickfix. Poor coding was referring to the fact that this method was setting two lists, treq and deptList not that I am trying to use Raw. – jeff Sep 03 '15 at 21:47
  • I updated my fix with your new method. I'm assuming `trDao.getList()` returns a `List` - if it doesn't, you'll need to fix that method before you can fix this method. There's nothing wrong with needing to clean up old code, but it has to be a conscious process - if you just run quick fixes you'll introduce as many bugs as you address. See the link in my previous comment if you're unclear what raw types are. – dimo414 Sep 03 '15 at 22:15
  • I get it now. The .add was the difference between code in which one quickfix worked as expected and the other gave me the wild card, because the .add was explicitly one type. I do the quickfixes one at a time, but out of laziness of typing what I knew it should be. And no, List treq = new ArrayList<>(); should be List treq = new ArrayList<>(); because trDao.getList() returns List so I will manually have to change Eclipse's > to in the getList() method. – jeff Sep 03 '15 at 22:44