How to avoid unchecked cast warnings with Java Generics

Related searches

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?

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.

Item 27: Eliminate unchecked warnings, I don't think you can do anything about this. You have to cast here, and in the process you lose all information about the type parameter: The compiler can't know� That code works very well, but I do get a warning from the compiler in the next() method in the line I marked. It is clear to me why this warning occurs, but I have not come up with any solution on how to solve the problem without this warning (save suppressing the warning). Any ideas?

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.

How can I avoid unchecked cast warning in my generic recursive , I would like to avoid Eclipse warnings, if possible. I read somewhere I could use SupressWarning to do it, what is it and how to use it? java� How to avoid unchecked cast warnings with Java Generics. Written by Rudy D'hauwe on August 10, 2013.. If you've ever made a serious effort to get rid of unchecked warnings from the Java compiler then you'll probably have found some cases where you know a cast is unavoidable yet correct but you can't convince the compiler of it.

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);

How do I address unchecked cast warnings?, If you've ever made a serious effort to get rid of unchecked warnings from the Java compiler then you'll probably have found some cases where� The compiler will gently remind you what you did wrong: Venery.java:4: warning: [unchecked] unchecked conversion Set<Lark> exaltation = new HashSet (); ^ required: Set<Lark> found: HashSet. You can then make the indicated correction, causing the warning to disappear.

How to avoid unchecked cast warnings with Java Generics, @Mr_and_Mrs_D (Location) data is type safe since Location is not generic type, unchecked cast warning is emitted only when casting to a generic type since the type argument is lost due to type erasure (and only List "remains" in your case). – Katona Sep 9 '13 at 20:17

Normally the unchecked-conversion-warnings are very helpful to find code-parts that can be improved. But in this case I don't see a way without suppressing this warning. – Mnementh Jul 15 '09 at 12:03

You don't have to perform the unchecked cast. If it's certainly necessary, then at least try to limit the scope of the @SuppressWarningsannotation. According to its Javadocs, it can run on local variables; this way, it doesn't even affect the entire method. Example: @SuppressWarnings("unchecked")

Comments
  • Yes yes, I understand your point. I would like to use the generic type L for instanciating my Extractor. So instead of giving the "colType" into the getInstance method, I would like to do some thing like getInstance(L) and getInstance(R)... Is that possible? I hate supressing warnings!
  • @Sauer: You'd have to know L and R at execution time, which normally means having constructor parameters of type Class<? extends L> and Class<? extends R> or something similar.
  • One possibility is to have the constructor take the extractors it needs: PickMap(String sql, Extractor<? extends L> leftExtractor, Extractor<? extends R> rightExtractor>). This not only makes the compilation safe, it also lets someone else come along and decide they want a PickMap<BigDecimal,Date> without having to change the PickMap code (assuming Extractor is an interface or class they have access to).