Using interfaces over classes - java

I'm a bit confused about the advice to use the Interface for a Java class, like in this thread: Why should the interface for a Java class be preferred?
I understand why you would want to use the interface: if something changes later you have less code to clean up.
But aren't there cases in which using the Interface would prevent you from being able to take advantage of the performance reason why you chose that particular class in the first place?
For instance, if I have a TreeMap, I assume that I should be able to locate any element in at most O(logn). That's why it has nice methods I can take advantage of like higherEntry(), lowerEntry(), lastEntry().
If I instead reference this TreeMap as a Map, now I believe I am forced to iterate one element at a time through my list in O(n) to locate that entry.
I'm new to Java, so let me know if I'm missing something here.

If I instead reference this TreeMap as a Map, now I believe I am
forced to iterate one element at a time through my list in O(n) to
locate that entry.
No you are not forced to do that. If you are sure that your Map reference is holding a reference to TreeMap, and you want to access specific method of TreeMap, then you can always typecast the Map reference to a TreeMap reference, and then access the appropriate method, like, higherEntry(), lowerEntry().
But, the only caveat is that, you have to be sure that your Map reference is actually pointing to a TreeMap, to avoid getting a ClassCastException at runtime.
This is implied by the fact that, a super class and it's sub classes are covariant in nature. So, you can perform cast between them, provided you are not breaking the rules at runtime (That is having the super class reference holding the reference to some other sub class instance, which is not covariant with the sub class you are casting to).
Now for your example, since the TreeMap also implements the NavigableMap interface, which is a sub interface of Map interface, so you can use it instead of Map interface. So, you can have the advantage of polymorphism, without the need to typecast.

If you want to use methods like higherEntry, lowerEntry, and lastEntry, then just use the NavigableMap interface instead of the Map interface or the TreeMap class.
In general, use interfaces as often as possible, and use the most general interface you can that supports all the operations you'd want to use.

Related

How to create multimap of general datatype value in Java

I want to create a multimap where value could be general data type. For eg:
MultiMap<String,Integer> columnvalueMapList = new MultiMap<String,Integer>();
Here instead of integer, i want to make general data type. How can i do so?
You can use Object as a value type in a Map. However this is rarely a good idea as you will likely end up needing instanceof and casts to make use of the objects you extract.
Often the motivation for this is to be able to store objects of different classes without a common superclass. However a better option in these situations is to use an interface to define the common behaviour for all items in the collection. Then any classes that could be added to the collection must implement that interface. You then declare your collection as, for example, List<CommonInterface>. This is safer, clearer and easier to understand.

Passing List or ArrayList of objects

List<Kevin> kevin = new ArrayList<Kevin>();
I have an List of Objects of Type Kevin, now does it make any difference on what i am passing to my method?.
void method1(List<Kevin>)
void method2(ArrayList<Kevin>)
It seems that both are working, is there any difference apart from that i would have access to List interface related methods on method1 and array list related methods on method2. I am just not sure whether we need to send List or ArrayList of objects.
They will both behave the same way. It's generally preferable to code to interfaces where possible, so prefer List<Kevin> (or even Iterable<Kevin> if you just need to iterate over the collection). If your method will only function properly if it's an ArrayList<Kevin>, that's fair enough... but otherwise, it's better not to restrict the caller to force them to pass in an ArrayList.
method1 will work fine for other implementations of List as well (e.g. LinkedList), while method2 is stricter and accept only one implementation. In general, try to make your method arguments as general as possible, for re-usability reasons.
In most cases, it doesn't practically matter. An ArrayList IS a List so any functionality you get from a List you will also get from an ArrayList. And I should note, by the same principal, you may not actually get an ArrayList but rather some subclass that inherits from ArrayList (just like if you said List).
That said, it is typically considered best practice to require the most general type you need. So, if you only need methods that List provides, then pass a List object, however, if there is something specific to ArrayList that you require then pass that.
Passing an ArrayList would prevent you (or at least, make it more difficult) to change your mind and use another kind of List later, because method2() would rely on the list to be of type ArrayList, and not simply List.
Among the other List implementations that you could want to pass are LinkedList, CopyOnWriteArrayList, Arrays.asList(), Collections.synchronizedList(), or, often, Collections.unmodifiableList().
The best practice is thus to program on interfaces, and pass a List (or even a Collection or Iterable if calling methods should not even assume it's a List).
For a private method inside the same class, it doesn't matter much. But if the method is part of a public API, then passing an ArrayList could really hurt you at some time.

Return ArrayList or List?

I'm creating a library to be used by people but why should my method return a List instead of an ArrayList?
Because if the user knows the real type is an ArrayList he will use the accessor [] in a loop instead of iterator but if he doesn't know he will use an iterator.
Same question for LinkedList, if the return type is a List he won't be able to use the correct accessor.
Am I right?
Returning List will make it possible for users of your library to use anything that implements a List interface, while using an ArrayList will force them to use an ArrayList.
If in the future, you as a library creator decide to change your internal implementation, that changes will be hidden from the end user by the generic interface to your library.
Because the users of your library should never know that you are using an ArrayList internally.
For example, say you return an ArrayList and lots of people have started using your library. Now if you suddenly realize a LinkedList better suits your purpose, then you break compatibility for all the folks who are presently using your code.
This is why it is always better to code to an interface, not an implementation, and even more so when you are writing code that is specifically meant to be re-used. The interface (List in this case) acts as a contract between your code and the client's code. It tells them what your code does (interface), without telling them how it does it (by not exposing the implementation).
Return an interface (or failing that a super class?) if possible. This way the method can have a broader application if overriden. This might prevent some class-specific methods from being available on the returned object but there's nothing stopping a programmer taking the List data and copying it to whatever Collection they prefer to use.
List myList = new MyLibrary().getList();
ArrayList myArrayList = new ArrayList(myList);
LinkedList myLinkedList = new LinkedList(myList);
They don't have to use an iterator - the List interface supports get(int index) as a method. If you want flexibility to change the underlying container to anything supporting the list interface, use List. If specific ArrayList methods are required on what you return, use ArrayList.
Because your user can make from your List either ArrayList or LinkedList, you will leave him a choice. It's called Programming to Interface. You should give users of your API as much freedom as you can and this technique is one of the ways how to achieve it.
1. Its the concept of Interface Polymorphism.
2. Its better to have List<My_Obj> arr = new ArrayList<My_Obj>;
3. Suppose you want to use LinkedList instead of ArrayList as somepoint, then you donot
need to worry abt how to do it..
If You are returning List then it is possible for users of your library to use anything that implements a List interface. It may be Array List or Linked List.
I typically choose the most general type possible. In this case, you could return a type that's even more general than a List, such as Collection or Iterable.
By returning Iterable, the compiler will prevent the calling code from attempting to add elements to your list. This is much stronger than relying on Collections.unmodifiableList() to fail at runtime.
Using more general types also gives you more room to manoeuvre in the future. Perhaps your method's going to load your data from a streaming source rather than an in-memory source: then Iterable becomes a much more suitable than List.

Java overriding two interfaces, clash of method names

I am implementing the Map<V,K> and the Collection<V> interface in one class, but the remove(Object) method occurs in both interfaces, therfore eclipse shows me some errors. The return types are different, one returns boolean and the other V but that doesn't seem to matter.
Is there some way of telling java/eclipse which method is actually being overridden?
EDIT: I have got an interface that all values must implement, it supplies the value with a getKey() method, making it possible to write an add function for the map. But there seems to be no way to let this one class look as a map and a collection at the same time?
No, there is no a direct way.
Actually dynamic binding takes into account the signature excluding the returning type so Java compiler cannot accept the two methods for the same class that have same signature but different return types. If two methods have same names and same parameters than they MUST also have same returning type, unfortunately for you.
The only way is to split the behavior in two different classes and composing them. Maybe a method like Collection<V> asCollection() or something like that.
The Map already has keySet() which is collection of keys. Why do you need the Collection also? If it's so, just do two methods like asMap and asCollecton which do return different types.
No, there isn't a way to resolve such conflicts.
You should consider to use composition and delegation instead of inheritance for at least one of the two interfaces, or you could split the functionality of your class in two classes, it really depends on your concrete problem.
You probably need composition instead of inheritance. Unfortunately Java has no language-level support for that - I mean it can be done but it is unnecessarily laborious.
You need to rethink your design. Fundamentally, a map is different to a collection. Think about the Collection.add() method. Does it make any sense to add an object without a key or a key without a value to a map?
Your best bet (I think and depending on your application) is to implement a map but when you need a collection, use one of its methods to get the set of keys, values or key value pairs.

Java Variable type and instantiation

This has been bugging me for a while and have yet to find an acceptable answer. Assuming a class which is either a subclass or implements an interface why would I use the Parent class or Interface as the Type i.e.
List list = new ArrayList();
Vehicle car = new car();
In terms of the ArrayList this now only gives me access to the List methods. If I have a method that takes a List as a parameter then I can pass either a List or an ArrayList to it as the ArrayList IS A List. Obviously within the method I can only use the List methods but I can't see a reason to declare it's type as List. As far as I can see it just restricts me to the methods I'm allow to use elsewhere in the code.
A scenario where List list = new ArrayList() is better than ArrayList list = new ArrayList() would be much appreciated.
You write a program that passes lists around several classes and methods. You now want to use it in a multi threading environment. If you were sensible and declared everything as List, you can now make a single change to one line of code:
List list = Colllections.synchronizedList(new ArrayList());
If you had declared the list as an ArrayList, you would instead have to re-write your entire program. The moral of the story - always program to the least restrictive interface that your code requires.
Using the interface or parent type is generally recommended if you only need the functionality of the parent type. The idea is to explicitly document that you don't really care about the implementation, thus making it easier to swap out the concrete class for a different one later.
A good example are the Java collection classes:
If you always use List, Set etc. instead of e.g. ArrayList, you can later switch from ArrayList to LinkedList if you find that it gives e.g. better performance. To do that, just change the constructors (you don't even have to change them all, you can mix). The rest of the code still sees an instance of List and continues working.
If you actually used ArrayList explicitly, you'd have to change it everywhere it's used. If you don't actually need an ArrayList specifically, there's nothing to be gained from using it over the interface.
That's why it's generally recommended (e.g. in "Effective Java" (J.Bloch), Item 52: "Refer to Objects by their interfaces".) to only use interfaces if possible.
Also see this related question: Why classes tend to be defined as interface nowadays?
The key is exactly that the interface or base class restricts what you can do with the variable. For example, if you refactor your code later to use another implementation of that interface or base class, you won't have anything to fear -- you didn't rely on the actual type's identity.
Another thing is that it often makes reading the code easier, e.g. if your method's return type is List you might find it more readable to return a variable of type List.
An interface specifies a contract (what does this thing do), an implementation class specifies the implementation details (how does it do it).
According to good OOP practice, your application code should not be tied to implementation details of other classes. Using an interface keeps your application loosely coupled (read: Coupling)
Also, using an interface lets client code pass in different implementations and apply the decorator pattern using methods like Collections.synchronizedList(), Collections.unmodifiableList() etc.
A scenario where List list = new
ArrayList() is better than ArrayList
list = new ArrayList() would be much
appreciated.
One concrete example: if it's a field declaration and you have a setList(), which of course should take a List parameter to be flexible.
For local variables (and fields with no setters), there is very little concrete benefit in using the interface type. Many people will do it anyway on general principle.
You were right. In these cases, the variables are fields or local variables, they are not public interface, they are implementation details. Implementation detail should be detailed. You should call an ArrayList an ArrayList, because you just deliberately chose it for your implementation.
People who recycle cliches: look at your post and think a little bit more. It's nonsense.
My previous answer that was downvoted to death:
Use interface or type for variable definition in java?

Categories