Hi All,

I am just learning Java and there is a concept that I cannot grasp. I am writing a simple exercise program that works with stacks. I have a sum method for two different types - Integer and Double. They both have the same logic, so it seems redundant to do it this way. I thought it would be possible to write one method that takes either type. So I have read about generics and still cannot figure out a solution. Is it at all possible?

Here are my add methods:

// Return the sum of the stack
  public static Integer sum (Stack<Integer> stack) {
    Integer sum = 0, current;
    Stack<Integer> temp = new Stack<Integer>(); 
    
    // calculate the sum
    while (!stack.empty() ) { 
      current = stack.pop();
      sum = sum + current;
      temp.push(current);
    }
    
    // rebuild the stack
    while (!temp.empty()) { 
      stack.push(temp.pop());
    }
    
    return sum;
  }
  
  // Return the sum of the stack
  public static Double sum (Stack<Double> stack) {
    Double sum = 0.0, current;
    Stack<Double> temp = new Stack<Double>(); 
    
    // calculate the sum
    while (!stack.empty() ) { 
      current = stack.pop();
      sum = sum + current;
      temp.push(current);
    }
    
    // rebuild the stack
    while (!temp.empty()) { 
      stack.push(temp.pop());
    }
    
    return sum;
  }

Recommended Answers

All 23 Replies

Both the Integer and Double objects extend Number. So you could do the following:

public static Number sum (Stack<Number> stack) {

Note that this method will require you to check if the numbers are Integers or Doubles.

Also, remember that you can't use the + operation to add objects.

Why create a new stack in these methods. Just iterate thru the stack and add the elements?

int sum = 0;
for (int i: stack) {
  sum += i;
}

Here part of a possible solution.. the following compiles OK

public <T> T sum(Stack<T> stack) {
	T sum;  // really want to say    T sum= 0;
	for (T num : stack){
		// can't do this:  sum += num;
	}
	return sum;
}

ie, that's how you declare a method to take a Stack of Somethings, and return a Something result. What I can't figure out is how to do arithmetic on the Somethings. You can declare <T> as <T extends Number>, which is closer to the right spirit, but still doesn't get you any arithmetic capabilities. Ideas anyone?

It does get you arithmetic capabilities from within another class where you instantiate an Object of that generic class.

Hi BJSJC. What I mean is that with a variable defined as generic type <T extends Number> all you can access at compile time are the methods defined on Number itself, which do not seem to include any arithmetic functions. Do you know of another class that we could use to restrict <T> so that it includes Integer and Double and also gives arithmetic?
James

With the class you have defined, you can use something like. .

public int addInteger(){
		int result = 0; 
		for (T i: numbers){
			Integer j = (Integer)i;
			result+=j;
		}
		
		return result;
	}

This is where 'numbers' is defined as an ArrayList<T>.

Yes, you can do that, but what when you want to return a value of type T? If you define the result as Integer, that's OK, you can then do the same thing for Double, that's OK too, now you have overloaded methods that will work, but that's not what the OP was asking.

You can try this

public <T extends Number> T sum(Stack<T> stack) {
	Integer sum = 0;
	for (T num : stack){
		Integer n = (Integer) num;
		sum += n;
	}
	return (T) sum;
}

and hope that if <T> happens to be Double then the value won't overflow, or do the same thing with Double temp variables, and hope there's no rounding problems, and no runtime cast errors...

commented: Helpful, thanks! +2

What you want to do does not make sense then. You wouldn't expect the ArrayList class, which is generic, to add up all of the numbers in the array for you. The purpose is to provide a container, not to have specific implementations.

Sorry, obvious misunderstanding here. The method does the addition, or tries to, but is stymied by the problem of doing arithmetic on generic types.The ArrayList bit is almost irrelevant. The quest is to write a method that takes a generic parameter type, performs some arithmetic on it, and returns a result of the same type. Sure you can write n overloaded methods, but to OP wanted to know if there was a single method solution using generics. (ps, I don't think there is).
J

BestJewSinceJC, thank you for the lectures. I will sure read them.

JamesCherrill, thank you for your version of the code. I didn't know the extended for loop is applicable to stacks and queues, that will clean up my code. Regarding your proposed solution - it almost works. It works fine with Integers the way you posted it, however it gives a runtime error if I pass a Double to it:
java.lang.Double cannot be cast to java.lang.Integer.
May be I didn't exactly understand you comments? In any case, thank you for helping!

You can write an equivalent method that takes an array of Doubles. James' comment was making the point that by doing so, you are not really writing "generic" code. Generic code should provide methods that can work for any type of Object. Hence, it is "generic". If you read the lectures you'll gain a better understanding of what I'm talking about.

I didn't know the extended for loop is applicable to stacks and queues

Yes, it works for everything that implements the Collection interface. In fact the code I posted can have the parameter as Collection<T> rather than Stack<T> and will then be more widely useful.

Regarding your proposed solution - it almost works. It works fine with Integers the way you posted it, however it gives a runtime error if I pass a Double to it:

That's right - as I said "hope there's... no runtime cast errors" and after a bit more thought I'm even more convinced there is no sensible way to do what you ask. The only polymorphic way to do addition is via the + operator, that only works on primitives (int, double etc), but generics can only be reference types (Integer, Float etc)

That's right - as I said "hope there's... no runtime cast errors" and after a bit more thought I'm even more convinced there is no sensible way to do what you ask. The only polymorphic way to do addition is via the + operator, that only works on primitives (int, double etc), but generics can only be reference types (Integer, Float etc)

I think that if you use Number class instead of T, you can call methods such as doubleValue() and intValue(), then use the + operator and finally return either an Integer or Double. Number is an abstract class that both of these classes extend, so the true polymorphic method of doing what is required would be to use a Stack<Number> and return Number.

Hi Darkagn
Problem here is that Number is an abstract class, so you would have to chose a subclass (eg Integer) to instantiate a value to return. Number only has the xxxValue() methods, so you can't do much with it unles you know what subclass it really is. If the original data is Double, you need to calculate & return Double, ditto Integer, and there's no way I know to do that without explicitly coding both those cases - unless you have a better idea???
J

So in Java you can't declare that you will return an object of type Number, but actually return an Integer or Double (since they are subclasses)? Is that correct?

No, that is not correct. You can return any subclass of Number if the return type is declared as Number. But the point made earlier still stands.

No, that is not correct. You can return any subclass of Number if the return type is declared as Number.

If that is the case then I think my logic should work. If the method signature was like this:

public Number stackSum(Stack<Number> numbers)

Then I think it should be possible to have one method for both Integer and Double objects.

It is possible, but first, you have to verify the Object's type, then cast it. That isn't Generic code.

Ok I haven't tested this, but here is what I was thinking:

public Number stackSum( Stack<Number> numbers ) {
  String className = numbers.peek().getClass().getName();
  if( className.equals( "java.lang.Integer" ))
  {
    int sum = 0;
    className = "int";
  }
  else if( className.equals( "java.lang.Double" ))
  {
    double sum = 0;
    className = "double";
  }
  else
  {
    // problem, should probably throw a NumberFormatException or something
  }
  for( Number i: numbers )
  {
    if( className.equals( "int" ))
    {
      sum += numbers.get( i ).intValue();
    }
    else
    {
      sum += numbers.get( i ).doubleValue();
    }
  }
  if( className.equals( "int" )
  {
    return new Integer( sum );
  }
  else
  {
    return new Double( sum );
  }
}

EDIT: Just saw BJSJC's last post - yes this code isn't generic but is polymorphic. I didn't realise that the requirement was on generic code, I thought that the original poster just wanted to have one method for both Integer and Double.

Not trying to argue with you, just for the sake of a good discussion, I don't think it is polymorphic either. Polymorphic would mean that the method which gets invoked depends on the type of Object. (i.e. the classic example with Animals where which Animal's speak method gets called depends on what subclass (Dog, Cat, etc) of Animal the Object is). You are invoking the same method regardless of the type of Object.

Ah yes, good point. And I'm not trying to argue either, just trying to increase my understanding. Most of my recent programming has been in PHP, so just trying to keep my Java knowledge up to date. Sorry if I sounded argumentative.

No, you didn't sound argumentative.

:)

But we hijacked this thread. Oops.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.