6

I am trying to write a method in which I need to create a temp variable, sum, of generic type T. However, I'm getting the error "The local variable sum may not have been initialized". How can I initialize a generic variable? I can't set it to 0 or 0.0, and I can't find information anywhere on how to deal with this. Here is the portion of code that I'm working with:

public Matrix<T,A> multiply(Matrix<T,A> right) throws MatrixException
{
    Matrix<T,A> temp = new Matrix<T,A>(arithmetics, rowSize, columnSize);

    T sum, product;

    if (rowSize != right.columnSize)
        throw new MatrixException("Row size of first matrix must match column size " 
                + "of second matrix to multiply");

    setup(temp,rowSize,columnSize);

    for (int i = 0; i < rowSize; i++){
        for (int j = 0; j < right.columnSize; j++) {
            product = (arithmetics.multiply(matrix[i][j] , right.matrix[j][i]));
            sum = arithmetics.add(product, sum);
            temp.matrix[i][j] = sum;
        }
    }
    return temp;
}

I'm not sure if this will help clarify, but here is my interface Arithmetics:

public interface Arithmetics<T> {

public T zero();
public T add( T a, T b );
public T subtract( T a, T b);
public T multiply (T a, T b);
public T parseString( String str );
public String toString( T a );

}

And here is one of my classes, DoubleArithmetics, just to show how I'm implementing the interface:

public class DoubleArithmetics implements Arithmetics<Double> {

protected Double value;

public Double zero() 
{

    return new Double(0);
}

public Double add( Double a, Double b ) 
{

    return new Double(a.doubleValue()+b.doubleValue());
}

public Double subtract (Double a, Double b)
{
    return new Double(a.doubleValue()-b.doubleValue());
}

public Double multiply (Double a, Double b)
{
    return new Double(a.doubleValue()*b.doubleValue());
}

public Double parseString( String str )
{
    return Double.parseDouble(str);
}

public String toString( Double a )
{
    return a.toString();
}
}
woollyMammoth
  • 105
  • 1
  • 2
  • 7

2 Answers2

3

Just use the zero method that you already have on your interface to initialize sum:

T sum = arithmetics.zero();

For the non-zero initialization, you could also add methods that take long and double values and return the T for them:

public interface Arithmetics<T> {

    public T zero();
    public T create(long l);
    public T create(double d);
    public T add( T a, T b );
    public T subtract( T a, T b);
    public T multiply (T a, T b);
    public T parseString( String str );
    public String toString( T a );
}

And then implement them:

public Double create(long l) {
    return new Double(l);
}

public Double create(double d) {
    return new Double(d);
}

And finally, to use them:

T one = arithmetics.create(1);
Brian
  • 17,079
  • 6
  • 43
  • 66
  • By using methods in that way (namely, returning a specific type instead of the generic type), you are defeating the whole purpose of the generic container. The create() method should return type T. Implementations of Arithmetics should likewise have a create() that returns type T. – stackoverflowuser2010 Jun 30 '13 at 23:39
  • 1
    @stackoverflowuser2010 What are you talking about? My methods clearly return `T`, both of them are `public T create`. – Brian Jul 01 '13 at 02:05
  • The interface's create() method returns T. The implementation's method should also return T. In your code, your implementation's create() methods return Double. – stackoverflowuser2010 Jul 01 '13 at 05:49
  • 1
    Because the implementation has `implements Arithmetic` in his example, so I was showing an example implementation in line with his. – Brian Jul 01 '13 at 06:30
3

Instantiating generics in Java is a bit tricky due to type erasure.

My approach is to pass into your generic class' constructor two items: (1) a java.lang.reflect.Constructor specific to type T; and (2) an Object[] array holding a default value specific to type T.

When you later want to instantiate and initialize a type T, you need to call Constructor.newInstance(Object[]). In the code below, the MyGenericClass class stands in for your generic class (looks like it's called Matrix from your original post).

I got the solution from InstantiationException for newInstance() and Create instance of generic type in Java?

public class MyGenericClass<T>
{
    Constructor _constructorForT;
    Object[] _initialValueForT;

    public MyGenericClass(Constructor constructorForT, 
                          Object[] initialValueForT)
    {
        _constructorForT = constructorForT;
        _initialValueForT = initialValueForT;
    }

    public void doSomething() 
    {
        T sum = initializeT(_constructorForT, _initialValueForT);

        System.out.printf("d = %f\n", sum);
    }

    @SuppressWarnings("unchecked")
    private T initializeT(Constructor constructor, Object[] args)
    {
        T result = null;

        try
        {
            result = (T) constructor.newInstance(args);
        }
        catch (java.lang.InstantiationException ex)
        {
        }
        catch (java.lang.IllegalAccessException ex)
        {
        }
        catch (java.lang.reflect.InvocationTargetException ex)
        {
        }

        return result;
    }

    public static void main(String argv[]) throws Exception
    {
        Constructor constructor = 
            Double.class.getConstructor(new Class[]{double.class});

        Object[] initialValue = new Object[] { new Double(42.0) };

        MyGenericClass<Double> myGenericClass = 
            new MyGenericClass<Double>(constructor, initialValue);

        myGenericClass.doSomething();

    }
}
Community
  • 1
  • 1
stackoverflowuser2010
  • 38,621
  • 48
  • 169
  • 217