3

considering i have a method which gets a List passed as an param. Within this method i want to use for instance an ArrayList specific function on that list (lets say trimToSize()). What would be the general approach to deal with a problem like this ? Here two example:
First approach (i don't think this is good)

private void doSomething(final List<T> list) { // ... do something ((ArrayList<T>) list).trimToSize(); // ... do something } 

Second approach (i think this one is better)

private void doSomething2(final List<T> list) { final List<T> myList = new ArrayList<T>(); // Collections.copy(myList, list); or myList.addAll(list); ((ArrayList<T>) myList).trimToSize(); //..do something } 

I'm curious whats the best solution for a problem like this.

7
  • Why are you passing it as final? this should be causing you errors. Commented Feb 18, 2010 at 23:45
  • 3
    Marking an argument as final just means you cannot re-use that variable, that is assign it a new value. You can still use and modify (through method call, etc.) the value. Commented Feb 18, 2010 at 23:53
  • 1
    @MadMurf you're welcome. I got that piece of info in the same way you just did :D Commented Feb 19, 2010 at 0:28
  • 2
    Why do you want to call trimToSize? What if the object being passed in doesn't have a trimToSize method? Commented Feb 19, 2010 at 0:36
  • For C developers its best to think of final here as a 'int * const foo' as opposed to a 'int const * foo'. You can't change what the pointer points to, but you can modify the target of the pointer. See en.wikipedia.org/wiki/Const-correctness Commented Feb 19, 2010 at 0:39

8 Answers 8

12

Well, the preferred option is to just write the method to take an ArrayList in the first place. If you need ArrayList specific functionality, the method has no business taking a List. Transfer the responsibility of ensuring that the parameter is of the right type to the caller and don't fiddle around with it inside the method.

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

Comments

6

Why not just declare method as a private void doSomething(final ArrayList<T> list), if you want only ArrayList as parameter?

7 Comments

He wants to be able to accept a List as an argument, but he needs an ArrayList within the method body for a different reason (implementation-specific)
@David, then it makes no sense for the method to accept a List if it requires an ArrayList
@mattb: What I mean is that at the API level he wants this method to be able to accept any List. With the current implementation he has chosen his logic uses an ArrayList. The API should not be tied to the implementation as the implementation should be free to change. The fact that one type inherits the other is just a coincidence which is causing the confusion. Logically the 2 lists (the List and the ArrayList) are separate and just happen to contain the same entries.
If he wants it to accept any List then the only methods he should be calling internally in the function on the passed in object are those define in the List interface. Otherwise he's leaving himself open to errors when a non-ArrayList object is passed.
The API is tied to the implementation. It even does a cast. You're just causing a disaster waiting to happen if anything changes since the API advertises it takes a List but internally it assumes it is an ArrayList. Either specialize the method so it takes an ArrayList, or don't have it assume what gets passed in is an ArrayList
|
3

If you're accepting any object implementing the List interface then your function should only invoke methods implemented from the interface.

If you want to invoke functions from ArrayList class then have ArrayList as your parameter. Much safer than either of your options.

Comments

2

The second we have huge overhead with big lists, but is safer. I would go for the first, but with check whether the provided List is ArrayList and then make a cast.

You should have a strong reasons to not take an ArrayList as a parameter though.

Comments

2

The first option you've shown only works for ArrayLists so it's not an option if you want to support any type of List. If you want to support any type of List you must convert (not cast) it to an ArrayList.

I think there might be some confusion because the List and ArrayList are so closely related (by inheritance). It is only coincidence that the parameter type and the class we need to call the function on are related in this way.

If we abstract the requirements a bit:

  1. We need to act on a series of values
  2. We need to use trimToSize() on the series of values.

If the values were coming as an array there would be no question but to create a new ArrayList with the values from the array and then use trimToSize(), because casting would not be an option. It is just bad luck that the method we need trimToSize() happens to be on a subclass of List, and the author wants to pass the values as a List.

Comments

2

What about

private void doSomething(final List<T> list) { final ArrayList<T> arrayList; if (list instanceof ArrayList) { arrayList = (ArrayList<T>) list; } else { arrayList = new ArrayList<T>(list); } ... arrayList.trimToSize(); } 

Of course, I agree with Chinmay Kanchi: for a private method, it makes no sense to accept a more general type than necessary. My approach is only feasible if it causes no problems to modify the given list.

Comments

1

Your first method changes the List passed to the method while the other one doesn't. Two methods are not comparable.

Comments

0

Since it is a private method, the convention of using the List interface is not overly important. There is no public API affected so use whichever method is the most convenient for its usage in the class.

For example, if 5 other methods call this method with potentially varying types of List, then use your second option and centralize the conversion in 1 method (you can even throw in a check for type and not convert if you like). If your class only deals with ArrayList internally anyway, and you know that is what it will be when called, then declare it as a ArrayList and make your life easy for yourself.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.