Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Best Practices - Returning an Object vs. a Generic

I'm using Generics for the first time for a school project and I have come across a philosophical dilemma regarding whether to return objects or my declared generic element in my methods.

My OCD is telling me that I need to always return the known type but I'm finding that doing so creates some downstream annoyances when I feed primitive datatypes into my class (and, of course, for this project I'm only ever feeding primitives into this class).

Here's an example of what I mean:

public class DansPriorityQueue<E extends Comparable> 
{
    private ArrayList<E> tree;

//Here's a method that returns an object
public Object peek() {
    return tree.get(0);
}

//Here's a method that returns the generic type
public E peek() {
    return tree.get(0);
}

(As an FYI.. I'm required to implement this JDK class myself but I am fortunately not required to implement the same interfaces that the real PriorityQueue does so I do have a choice as to whether I want to use the Object or the generic)

My Issue

It makes me feel a little dirty but I'm tempted just to return an Object rather than my E generic element on these methods because when I return E, JUnit forces me to cast my integer values:

DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());

When I return an object on the other hand, the auto-boxing doesn't force me cast my primitive value.

Here's a more eloquent description of the issue I've been facing:

http://www.aschroder.com/2009/10/php-1-java-0-the-method-assertequalsobject-object-is-ambiguous-for-the-type/

------------EDIT----------------

Here's the actual error I receive when I return the generic type and fill my list with the autoboxed Integer object without the cast above: The method assertEquals(String, Object, Object) is ambiguous for the type DansPriorityQueueTest

--------- END EDIT--------------

Questions

  1. Can anyone tell me why I should or should not return an object as opposed to the generic element I'm working with? Both seem to have upsides and downsides... what's the best practice?

  2. I know vaguely that returning an Object can cause some casting issues later on but I've not yet run into them... does anyone have a specific example of how this can be dangerous?

  3. In the JDK, I've noticed that many of the Collections methods return Object by default. Is this because Generics was introduced in a later version of Java or was this a conscious decision by Sun Systems?

like image 666
DanK Avatar asked Nov 08 '13 15:11

DanK


People also ask

Is it OK to return Object Java?

In java, a method can return any type of data, including objects. For example, in the following program, the incrByTen( ) method returns an object in which the value of an (an integer variable) is ten greater than it is in the invoking object.

Why do we use generics instead of object?

Generics could be used to develop a better solution using a container that can have a type assigned at instantiation, otherwise referred to as a generic type, allowing the creation of an object that can be used to store objects of the assigned type.

What is the point of generics in Java?

Java Generics helps the programmer to reuse the code for whatever type he/she wishes. For instance, a programmer writes a generic method for sorting an array of objects. Generics allow the programmer to use the same method for Integer arrays, Double arrays, and even String arrays.

Is object a generic type?

Why Generics? The Object is the superclass of all other classes, and Object reference can refer to any object. These features lack type safety. Generics add that type of safety feature.


1 Answers

Can anyone tell me why I should or should not return an object as opposed to the generic element I'm working with? Both seem to have upsides and downsides... what's the best practice?

It depends. In a case like this you'd want to generic type - otherwise what's the point of defining generic type for the class?

I know vaguely that returning an Object can cause some casting issues later on but I've not yet run into them... does anyone have a specific example of how this can be dangerous?

Sure!

DansPriorityQueue<String> queue = new DansPriorityQueue<String>();
//add items
Float f = (Float)queue.getObject();  //uh-oh! this compiles but will fail 
Float f = queue.getObject(); //generic type, fails during compile

In the JDK, I've noticed that many of the Collections methods return Object by default. Is this because Generics was introduced in a later version of Java or was this a conscious decision by Sun Systems?

It's due to backward compatibility mostly, or for cases where you truly will use the collection to contain disparate values (a mishmash of say, JLabels, Strings and Icons for instance for rendering a JTable for instance).

assertEquals("Expected different size", (Integer) 2, dpq.size());

I don't think this should be a problem. dpq.size() should just return an int regardless off what is stored in the priority queue. It would not be a generic value.

You can create something like

DansPriorityQueue<Double> queue = new DansPriorityQueue<Double>();
for(double d = 0; d < 10; d+=1.0)
    queue.add(d);

and that should cause no issues, right?

like image 83
Markus Koivisto Avatar answered Sep 26 '22 00:09

Markus Koivisto