1

I'm attempting implement the add method mentioned in the Generic sparse matrix addition question

class Matrix<T extends Number>
{
  private T add(T left, T right)
  {
   if (left instanceof Integer)
   {
     return new Integer(((Integer)left).intValue() + ((Integer)right).intValue());
   }
}

The compiler errors with found java.lang.Integer Required T at the line where I return a new Integer. I'm not sure what I'm missing since T extends Number and Integer is a subclass of Number.

6
  • Cat extends Animal, and Dog is a subclass of Animal. That doesn't mean you can return a Dog where a Cat is expected. Commented Nov 20, 2011 at 17:18
  • @OliCharlesworth I've tried casting to T but that didn't seem to help Commented Nov 20, 2011 at 17:19
  • @NuclearGhost: What error did that give? Commented Nov 20, 2011 at 17:20
  • @SLaks I'm sorry I should say warning. Matrix.java:43: warning: [unchecked] unchecked cast found : java.lang.Integer required: T return (T) (new Integer(((Integer)left).intValue() + ((Integer)right).intValue())); Commented Nov 20, 2011 at 17:25
  • The compiler is warning you that that cast cannot be checked at runtime. There is no way to avoid that warning; you should suppress it. Commented Nov 20, 2011 at 17:26

4 Answers 4

4

The compiler doesn't let you do this because T might be some other class, such as Double.
You know that T is Integer from the instanceof check, but the compiler doesn't.

Sign up to request clarification or add additional context in comments.

Comments

3

Java's type system is simply not capable of expressing this. Here is a work around.

Create an interface Numeric that provides the numeric operations you are interested in, and write its implementations for the data types you are interested in.

interface Numeric<N> {
  public N add(N n1, N n2);
  public N subtract(N n1, N n2);
  // etc.
}

class IntNumeric extends Numeric<Integer> {
  public static final Numeric<Integer> INSTANCE = new IntNumeric();

  private IntNumeric() {
  }

  public Integer add(Integer a, Integer b) {
    return a + b;  
  }

  public Integer subtract(Integer a, Integer b) {
    return a - b;  
  }

  // etc.
}

And rewrite your Matrix class constructor to accept this implementation.

class Matrix<N> {
  private final Numeric<N> num;
  private final List<List<N>> contents;

  public Matrix(Numeric<N> num) {
    this.num = num;
    this.contents = /* Initialization code */;
  }

  public Matrix<N> add(Matrix<N> that) {
    Matrix<N> out = new Matrix<N>(num);
    for( ... ) {
      for( ... ) {
        out.contents.get(i).set(j,
          num.add(
            this.contents.get(i).get(j),
            that.contents.get(i).get(j),
          )
        );
      }
    }
    return out;
  }
}

// Use site
Matrix<Integer> m = new Matrix<Integer>(IntNumeric.INSTANCE);

Hope that helps.

Comments

0

"I'm not sure what I'm missing since T extends Number and Integer is a subclass of Number."

This statement is false. In general if you have:

 public class B extends A {
 }

 public class C extends A {
 }

it does not mean that B can be cast to C. So writing something like:

 public <T extends A> T method(T arg) {
     return (B)arg;
 }

and you calling it with B b = (B)method(C); is obviously wrong.

1 Comment

Ah yes that is correct. Just because they extend the same thing does not make them the same.
-3

package generics;

public class Box<T> {

      public T j,k;
      int l;
      float f;

      @SuppressWarnings("unchecked")
    public void add(T j,T k) {
        this.j = j;
        this.k=k;

        if(j.toString().contains("."))
        {
              this.f=Float.parseFloat(j.toString())+Float.parseFloat(k.toString());


        } else{
        this.l=Integer.parseInt(j.toString())+Integer.parseInt(k.toString());
        }
      }

      public int getInt() {
        return l;
      }

      public float getFloat() {
            return f;
          }

      public static void main(String[] args) {
         Box<Integer> integerBox = new Box<Integer>();
         Box<Float> floatBox = new Box<Float>();

         integerBox.add(new Integer(10),new Integer(20));
         floatBox.add(new Float(2.2),new Float(3.3));

         System.out.printf("Integer Value :%d\n\n", integerBox.getInt());
         System.out.printf("float Value :%f\n", floatBox.getFloat());
      }
    }

1 Comment

You shouldn't post code without any explanation what it does and how it could/should solve the question. And by the way, you also shouldn't add @SuppressWarnings("unchecked") to your code, because you get that on purpose. And another thing: Your code is very vulnerable for an Exception.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.