1

I have two classes that use generics in Java in order to perform conversions between units of measure. In the BaseUnitConverter class I have two warnings, from the intellij IDE, that say:

Raw use of parameterized class 'InstantiatorUnitConverter' 
Unchecked assignment: 'org.cnr.lambertools.utils.unitconverter.InstantiatorUnitConverter' to 'org.cnr.lambertools.utils.unitconverter.InstantiatorUnitConverter<T>' 
Unchecked call to 'InstantiatorUnitConverter(Object, T, String)' as a member of raw type 'org.cnr.lambertools.utils.unitconverter.InstantiatorUnitConverter' 

for methods:

protected final <M,E> M storeValue(M t, double value, E tt){
        me = new InstantiatorUnitConverter(value, tt, st(tt));
        return t;
    }

and

protected final <M, E> M storeValue(M t, Object value, E tt){
    me = new InstantiatorUnitConverter(value, tt, st(tt));
    return t;
}

enter image description here

The basic classes of this conversion system are as follows:

import java.io.Serializable;

/**
 * Instantiated variables from new UnitConverter instance (Only used in class BaseUnitConverter).
 */
public final class InstantiatorUnitConverter<T> implements Serializable {
    private final Object o;      //Only used in DataType and NumericBase measurements (classes), user passed "from" value (Object). When this is the case, variable "v" is not used.
    private final double v;      //User passed "from" value (double). When this is the case, variable "o" is not used.
    private final T t;        //Enum constant value representing the "from" method of the measurement used.
    private final String ts;  //String value of enum constant representing the "from" method of the measurement used.
    private final boolean d;  //Used in class B.java "getValuePassed()". True if "from" value was a double, false for Object (Object only used in DataType and NumericBase measurements (classes)).

    /**
     * Empty constructor only called when instantiating from class B.java
     */
    public InstantiatorUnitConverter(){
        o = "";
        v = -1;
        t = null;
        ts = "";
        d = true;
    }

    /**
     * Only used in class B.java when measurement "from" method only converts numbers.
     * All measurements other than DataType and NumericBase use this constructor.
     * @param value User passed "from" value (double).
     * @param enumConstant Enum constant value representing the "from" method of the measurement used.
     * @param enumTag String value of enum constant representing the "from" method of the measurement used.
     */
    public InstantiatorUnitConverter(double value, T enumConstant, String enumTag){
        o = "";     //This variable (Object value) will not be used when this constructor is called, default it to an empty string.
        v = value;
        t = enumConstant;
        ts = enumTag;
        d = true;   //Variable d set to true as "from" value passed is a numeric type not an Object.
    }

    /**
     * Only used in class B.java when measurement "from" method can convert more than numbers and an Object is passed as the value.
     * Only measurements DataType and NumericBase use this constructor.
     * @param value User passed "from" value (Object).
     * @param enumConstant Enum constant value representing the "from" method of the measurement used.
     * @param enumTag String value of enum constant representing the "from" method of the measurement used.
     */
    public InstantiatorUnitConverter(Object value, T enumConstant, String enumTag){
        o = value;
        v = -1;     //This variable (double value) will not be used when this constructor is called, default it to -1
        t = enumConstant;
        ts = enumTag;
        d = false;  //Variable d set to false as "from" value passed is an Object not double.
    }


    public Object getO() {
        return o;
    }

    public double getV() {
        return v;
    }

    public T getT() {
        return t;
    }

    public String getTs() {
        return ts;
    }

    public boolean isD() {
        return d;
    }
}

and

import java.io.Serializable;

/**
 * Generic base class for most UnitConverter measurement classes.
 */
public class BaseUnitConverter<T> implements Serializable {

    private InstantiatorUnitConverter<T> me; //Instantiate class A.java for variables needed to perform conversions.

    public BaseUnitConverter() {
        this.me = new InstantiatorUnitConverter<>();
    }

    public InstantiatorUnitConverter<T> getIstantiator(){
        return this.me;
    }

    /**
     * Returns value initially passed into the measurement's "from" method.
     */
    public final Object getValuePassed(){
        return (me.isD()) ? me.getV() : me.getO();    //true returns numeric value passed, false returns Object passed.
    }

    /**
     * Returns the enum constant value representing the "from" method of the measurement used.
     */
    public final String getTypeConstantPassed(){

        return me.getTs();
    }

    /**
     * Stores the needed values to do conversions of the measurement.
     * This overload of the method is used in "from" methods in every measurement class other than Anything(), DataType(), and NumericBase().
     *
     * @param <M> Class context of measurement passed (usually "this" is passed from caller).
     * @param <E> Enum constant value representing the "from" method of the measurement used.
     * @param t Class context of measurement passed (usually "this" is passed from caller).
     * @param value User passed "from" value (double).
     * @param tt Enum constant value representing the "from" method of the measurement used.
     * @return class context passed in so variable like "UnitOf.Length len" can be used as the variable type
     */
    protected final <M,E> M storeValue(M t, double value, E tt){
        me = new InstantiatorUnitConverter(value, tt, st(tt));
        return t;
    }

    /**
     * Stores the needed values to do conversions of the measurement.
     * This overload of the method is used only in DataType and NumericBase as Objects can be passed as "from" values.
     *
     * @param <M> Class context of measurement passed (usually "this" is passed from caller).
     * @param <E> Enum constant value representing the "from" method of the measurement used.
     * @param t Class context of measurement passed (usually "this" is passed from caller).
     * @param value User passed "from" value (Object).
     * @param tt Enum constant value representing the "from" method of the measurement used.
     * @return class context passed in so variable like "UnitOf.DataType dt" can be used as the variable type
     */
    protected final <M, E> M storeValue(M t, Object value, E tt){
        me = new InstantiatorUnitConverter(value, tt, st(tt));
        return t;
    }

    /**
     * Gets and returns the string value of constant representing the "from" method of the measurement used.
     */
    private <E> String st(E tt){
        String unitType = "";
        try{
            unitType = tt.toString();
        } catch(Exception ignored){ }
        return unitType;
    }

    /**
     * Used by every measurement class that converts just numbers (Anything(), DataType(), NumericBase() do not apply here).
     * Method performs the full conversion of taking the user defined "from" value and converting it into the user desired "to" value.
     * @param a Enum constant value of "to" unit. Unit being converted into conversion constant value.
     * @param b Enum constant value of "from" unit. Unit starting from conversion constant value.
     * @return Finished conversion. "From" converted into "to" value.
     */
    protected final double k(double a, double b){

        return k(a,b,true);
    }

    /**
     * Used by every measurement class that converts just numbers (Anything(), DataType(), NumericBase() do not apply here)
     * Method performs the full conversion of taking the user defined "from" value and converting it into the user desired "to" value.
     * @param a Enum constant value of "to" unit. Unit being converted into conversion constant value.
     * @param b Enum constant value of "from" unit. Unit starting from conversion constant value.
     * @param q Multiply then divide conversion algorithm, false will divide then multiply when converting "to"
     * @return Finished conversion. "from" converted into "to" value.
     */
    protected final double k(double a, double b, boolean q){

        return UnitConverterUtils.i(UnitConverterUtils.i(me.getV(), a, q), b, !q);
    }


}

I tried the solution proposed by Serg Vasylchak but I got an error message (note just change letter symbols):

enter image description here

enter image description here

Gianni Spear
  • 7,033
  • 22
  • 82
  • 131

1 Answers1

0
    protected final <M,E> M storeValue(M t, double value, E tt){
        me = new InstantiatorUnitConverter<E>(value, tt, st(tt));

        return t;
    }

Raw use of parameterized class 'AClass' means you have a class AClass<T> parameterized definition, but reference it without a "diamond" - AClass a = new AClass()

Some more examples of raw use:

        List list = new ArrayList<>(); // --> List<?> list
        List<String> list = new ArrayList(); // --> new ArrayList<>();
        Function function = o -> o.toString(); // --> Function<Object, String>

EDIT

You have a generic class

class BaseUnitConverter<T> {

    private InstantiatorUnitConverter<T> me;

    protected final <M, E> M storeValue(M t, double value, E tt) {
        this.me = new InstantiatorUnitConverter<E>(value, tt, st(tt));
        return t;
    }
}

The problem is that you pass the E type to be assigned to a T-typed reference.

It is the same as if you did List<String> list = new ArrayList<Integer>();

I now see 2 ways to fix it, but it depends on your specifics.

  1. Make storeValue accept T as a parameter (you will lose type flexibility though)
class BaseUnitConverter<T> {

    private InstantiatorUnitConverter<T> me;

    protected final <M> M storeValue(M t, double value, T tt) {
        this.me = new InstantiatorUnitConverter<>(value, tt, st(tt));
        return t;
    }
}
  1. "De-generify" the BaseUnitConverter class (you will have to cast at some point, the same way it works in Java Collections)
class BaseUnitConverter {

    private InstantiatorUnitConverter<?> me;

    protected final <M, E> M storeValue(M t, double value, E tt) {
        this.me = new InstantiatorUnitConverter<>(value, tt, st(tt));
        return t;
    }

    // You will lose the type here
    public InstantiatorUnitConverter<?> getIstantiator(){
        return this.me;
    }

    // Or generify the getter 
    // May throw java.lang.ClassCastException if referencing with the wrong type
    // Java-collections-like style (e.g., see ArrayList)
    @SuppressWarnings("unchecked")
    public <T> InstantiatorUnitConverter<T> getIstantiator() {
        return (InstantiatorUnitConverter<T>) this.me;
    }
}
Serg Vasylchak
  • 858
  • 4
  • 18