Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid unchecked cast warnings with Java Generics

Somehow my old question was closed, so I open a new one:

I am using Java Generics to implement a generic bidirectional Hash Map out of an SQL Query. It should be able to map any combination of String, Integer pairs back and forth. It should be used like this:

String sql = "SELECT string_val, int_val FROM map_table";
PickMap<String, Integer> pm1 = new PickMap<String, Integer>(sql);

String key1 = "seven";
Integer value1 = pm1.getLeft2Right(key1);

Integer key2 = 7;
String value2 = pm1.getRightToLeft(key2);

Of course it should be possible to create an pm (Integer, Integer) and so on...

My implementation of Pick Map looks like this (without the getter...):

public class PickMap<L, R> {

    private final HashMap<L, R> left2Right = new HashMap<L, R>();
    private final HashMap<R, L> right2Left = new HashMap<R, L>();

    public PickMap(String sql) throws OException {
        DTable d = new DTable(sql);
        int colTypeL = d.t.getColType(1);
        int colTypeR = d.t.getColType(2);
        Extractor<L> extLeft  = (Extractor<L>) getInstance(colTypeL);
        Extractor<R> extRight = (Extractor<R>) getInstance(colTypeR);    
        int numRows = d.t.getNumRows();
        for(int i=1;i<=numRows;i++) {
            L leftVal = extLeft.extract(d, i);
            R rightVal = extRight.extract(d, i);
            this.left2Right.put(leftVal, rightVal);
            this.right2Left.put(rightVal, leftVal);
        }
    }

    private Extractor<?> getInstance(int type) {
        if(type == 1)
            return new IntExtractor();
        else
            return new StringExtractor();
    }
}

interface Extractor<E> {
    E extract(DTable source, int row);
}

class IntExtractor implements Extractor<Integer> {

    @Override
    public Integer extract(DTable source, int row) {
        int value = 5;
        return new Integer(value);
    }
}

class StringExtractor implements Extractor<String> {

    @Override
    public String extract(DTable source, int row) {
        String retVal = "hello";
        return retVal;
    }
}

I have no compiler errors and I'm pretty sure, that it will work this way. BUT I'm getting unchecked cast warnings on the "getInstance" methods Where I cast Extractor(E) to Extractor(L)...

How should I cast properly? Or what am I missing? Or should I just suppress those warnings?

like image 206
Sauer Avatar asked Feb 29 '12 13:02

Sauer


3 Answers

You're getting warnings because what you're doing can't be proved to be safe. You're assuming that getInstance(colTypeL) will return an Extractor<L> - but that can't be verified at either compile-time or execution time.

You can use @SuppressWarnings("unchecked") as mentioned by others, but I would try to rethink the design somewhat.

like image 54
Jon Skeet Avatar answered Oct 12 '22 18:10

Jon Skeet


You can use the following annotation to make the compiler not output those warnings:

@SuppressWarnings("unchecked")

See this related question which deals with the same issue. The answer there will explain everything you need to know.

like image 21
Richard Walton Avatar answered Oct 12 '22 20:10

Richard Walton


If you are using the Spring Framework, you can use CastUtils:

import static org.springframework.data.util.CastUtils.cast;
obj.setString(cast(someObject));
String bob = cast(someObject);
like image 30
user11058144 Avatar answered Oct 12 '22 18:10

user11058144