Just hoping I could get someone to tell me I am doing this right or not, as I have never written something like this before. So I have to write a class named ProcessQueue that is a subclass of Vector, as well as a constructor that will define an empty queue. Also the Vector will be holding items of type "Object." So here it is...
public class ProcessQueue<Vector>{
ProcessQueue(){}
}
Not, that's not right. That's generic, not extending.
Besides, it's not a good idea. Your ProcessQueue might have a collection of some sort underneath, but it need not extend. Prefer composition to inheritance.
If you must implement something, start by having an API that actually looks like a Queue. There's a certain behavior that's expected; make sure that yours conforms to it. The best way is to implement an interface that enforces it.
public class ProcessQueue<T> implements Queue<T> {
// Have a private collection of some sort that provides the behavior that the interface requires
}
You're not extending Vector anywhere. Change your code to:
public class ProcessQueue<T> extends Vector<T> {
}
By the way, I don't recommend you using Vector at all. Check Why is Java Vector class considered obsolete or deprecated?. IMO if you have to do this it would be better extending ArrayList.
public class ProcessQueue<T> extends ArrayList<T> {
}
And in your code use a List:
List<SomeClass> lstQueue = new ProcessQueue<SomeClass>();
U̶n̶r̶e̶l̶a̶t̶e̶d̶ ̶t̶o̶ ̶t̶h̶e̶ ̶o̶r̶i̶g̶i̶n̶a̶l̶ ̶q̶u̶e̶s̶t̶i̶o̶n̶ , I think similar as duffymo, you should not extend any of the Java Collection classes until it is a must-do. Note that there are plenty of classes to hold almost any kind of common collections, and you have Queue and PriorityQueue that can help you in your real work.
The best solution would be as pointed by duffymo, composition instead of extending a Java Collection:
public class ProcessQueue<T> {
private List<T> data = new ArrayList<T>();
//rest of code...
}
Or creating a new implementation of an interface, like Queue or List.
public class ProcessQueue<T> implements Queue<T> {
//Queue interface methods implementation...
}
Related
When I try to implement my own ImmutableList (actually a wrapper that delegates to the underlying list) I get the following compiler error:
ImmutableListWrapper is not abstract and does not override abstract method isPartialView() in com.google.common.collect.ImmutableCollection
But in fact, it seems to be impossible to override isPartialView() because it is package protected and I'd like to declare the wrapper in my own package.
Why don't I simply extend ImmutableCollection? Because I want ImmutableList.copyOf() to return my instance without making a defensive copy.
The only approach I can think of is declaring a subclass in guava's package which changes isPartialView() from package-protected to public, and then having my wrapper extend that. Is there a cleaner way?
What I am trying to do
I am attempting to fix https://github.com/google/guava/issues/2029 by creating a wrapper that would delegate to the underlying ImmutableList for all methods except spliterator(), which would it override.
I am working under the assumption that users may define variables of type ImmutableList and expect the the wrapper to be a drop-in replacement (i.e. it isn't enough to implement List, they are expecting an ImmutableList).
If you want your own immutable list but don't want to implement it, just use a ForwardingList. Also, to actually make a copy, use Iterator as parameter for the copyOf. Here's a solution that should fulfill all your requirements described in the question and your answer.
public final class MyVeryOwnImmutableList<T> extends ForwardingList<T> {
public static <T> MyVeryOwnImmutableList<T> copyOf(List<T> list) {
// Iterator forces a real copy. List or Iterable doesn't.
return new MyVeryOwnImmutableList<T>(list.iterator());
}
private final ImmutableList<T> delegate;
private MyVeryOwnImmutableList(Iterator<T> it) {
this.delegate = ImmutableList.copyOf(it);
}
#Override
protected List<T> delegate()
{
return delegate;
}
}
If you want different behavior than ImmutableList.copyOf() provides, simply define a different method, e.g.
public class MyList {
public static List<E> copyOf(Iterable<E> iter) {
if (iter instanceof MyList) {
return (List<E>)iter;
return ImmutableList.copyOf(iter);
}
}
Guava's immutable classes provide a number of guarantees and make a number of assumptions about how their implementations work. These would be violated if other authors could implement their own classes that extend Guava's immutable types. Even if you correctly implemented your class to work with these guarantees and assumptions, there's nothing stopping these implementation details from changing in a future release, at which point your code could break in strange or undetectable ways.
Please do not attempt to implement anything in Guava's Imutable* heirarchy; you're only shooting yourself in the foot.
If you have a legitimate use case, file a feature request and describe what you need, maybe it'll get incorporated. Otherwise, just write your wrappers in a different package and provide your own methods and guarantees. There's nothing forcing you, for instance, to use ImmutableList.copyOf(). If you need different behavior, just write your own method.
Upon digging further, it looks like this limitation is by design:
Quoting
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html:
Note: Although this class is not final, it cannot be subclassed as it has no public or protected constructors. Thus, instances of this type are guaranteed to be immutable.
So it seems I need to create my wrapper in the guava package.
I want to make a Graph consiting of Nodes in Java. The graph class will be used by different people and different algorithms, so we will need different Node classes for each case, let's say DefaultNode and SpecialNode extends DefaultNode.
Now I want DefaultNode to contain all the general stuff that a Node needs to work, like for example a list of direct neighbours. So I implement this list in DefaultNode:
List<DefaultNode> neighbours = new ArrayList<DefaultNode>();
My problem is now, that I obviously also need this list in the SpecialNode class, but there it should contain and return SpecialNodes. Of course I could overwrite the list and addNeighbour() as well as getNeighbours() methods in every class that inherits from DefaultNode, but that seems redundant and not how OOP is meant to work. I think this would be a perfect case to use templates (like in C++), but afaik there is no such construct in Java, leaving us with Generics.
The solution I came up with so far is the following:
interface INode {}
class DefaultNode<T extends INode> implements INode {
List<T> neighbours;
List<T> getNeighbours(){}
void addNeighbour(T node){}
}
here, the <T extends INode> brackets describe the possible neighbours of this node. So for a SpecialNode I would do:
class SpecialNode extends DefaultNode<SpecialNode> {}
now, while this seems to work as intended, it kind of feels strange... I was surprised that I could not find an easier solution, as this situation seems relatively common. How would you solve this? Is there a better/simpler approach that I missed? Or is the above a viable approach?
There is nothing wrong with your approach. In fact, some standard interfaces, such as Comparable are defined in exactly this way:
public class Fruit implements Comparable<Fruit> {
^^^^^ ^^^^^
If you want to force that the neighbours of a node are of the same type, you can use:
class DefaultNode<T extends DefaultNode<T>> implements INode
though I would make the interface generic (and just call it Node not INode).
We have a discussion in office and cannot understand which approach is better
I have a class (SomeClass) with some method which receives Serializable object. The signature is following:
public void someMethod(Serializable serializableObject){
...
}
And I need to call this method from another class, but I should provide it with some List as fact parameter. There are two different approaches
1. Serializable
private SomeClass someClass;
public void doSomething() {
List<String> al = new ArrayList<String>();
al.add("text");
someClass.someMethod((Serializable)al);
}
2. ArrayList
private SomeClass someClass;
public void doSomething() {
ArrayList<String> al = new ArrayList<String>();
al.add("text");
someClass.someMethod(al);
}
Benefit of the first example is that it adheres to the java’s best practices which says: use interface instead of concrete realization for reference type and any programmer while reading that source will understand that we don't need special behavior of the ArrayList. And the only place we need it's serializable behavior we are adding this behavior by casting it to the Serializable interface. And programmer can simply change this current realization of the List to some other serializable realization, for example, LinkedList, without any side affect on this element because we use interface List as it`s reference type.
Benefit of the second example is that we refer to ArrayList as to class which have not only List behavior but also Serializable behavior. So if someone looked at this code and tried to change ArrayList to List he would receive a compile time error which would reduce time for programmer to understand what is going on there
UPDATE: we can't change someMethod signature. It came from a third-party company and we use it not only for Serializable Lists but also for Strings, Integers and some other Serializable objects
You should use an interface when all you need is the methods an interface provides. (this is most cases) However, if you need more than one interface, you can use generics, but the simplest approach is to use the concrete type.
It's better to define ArrayList because this combines two interfaces - List + Serializable. You need both of them in one place.
It doesn't matter that much, but not that using interfaces should be applied more strictly for return types, and less strictly for local variables.
I would change the signature of the someMethod so that it reflects what it requires from the invoker of the method:
public class SomeClass {
public <T extends List<? extends Serializable> & Serializable> void someMethod(T t) {
}
public static void main(String[] args) {
SomeClass test = new SomeClass();
test.someMethod(new ArrayList<String>()); //Works
test.someMethod(new ArrayList<Image>()); //Compile time error, Image is not Serializable
List<String> l = null;
test.someMethod(l); //Compile time error
}
}
The signature of someMethod now says that you must invoke it with something that is a List, and that is Serializable, and contains elements that are Serializable
In this case, I would just use List, and not worry that the compiler cannot guarantee that your object is serializable (it most likely will be anyway, if you've done things right elsewhere).
Note that methods of the following type (which accept a Serializable parameter) provide a false sense of security, because the compiler can never guarantee that the entire object graph which needs to be serialized will actually be serializable.
public void write(Serializable s);
Consider an ArrayList (serializable) which contains non-serializable objects. The signature may as well just be:
public void write(Object o);
And then you don't have to worry about all the extraneous casting.
Also consider that, although you cannot change the signature of the API you are using, you can very easily create a wrapper API which has a different signature.
1 is generally the right thing to do. However in this case, my opinion would to be bend that and declare it as ArrayList<>. This avoids the cast and guarantees that someone can't change the implementation of the List to one that isn't Serializable.
You can't do (1) because you're not free to change the List implementation type arbitrarily, which is the whole idea of doing that. You can only use a List implementation that implements Serializable. So you may as well express that in the code.
(This is a hypothetical question for discussion, I have no actual problem).
Say that I'm making an implementation of SortedSet by extending LinkedHashMap:
class LinkedHashSortedMapThing extends LinkedHashMap implements SortedSet {
...
}
Now programmers who use this class may do
LinkedHashMap x = new LinkedHashSortedMapThing();
But what if I consider the extending of LinkedHashMap an implementation detail, and do not want it to be a part of the class' contract? If people use the line above, I can no longer freely change this detail without worrying about breaking existing code.
Is there any way to prevent this sort of thing, other than favouring composition over inheritance (which is not always possible due to private/protected members)?
I think the easiest way would be to make a private inner class that extends LinkedHashMap, and have LinkedHashSortedMapThing keep a reference to that and point all its methods there.
class LinkedHashSortedMapthing implements SortedSet {
private class Foo extends LinkedHashMap {
...
}
private Foo foo;
public void clear() {foo.clear();}
public boolean containsValue(Object value) {return foo.containsValue(value);}
...
}
If you extend a class, you inherit its public interface and there is no way to avoid this AFAIK. Composition would be the favourable solution indeed, as you are not supposed to depend on the internals of LinkedHashMap anyway - these can also change in future JDK versions.
Java has no private inheritance as C++ do (which is practically more or less equivalent to composition anyway).
You can implement SortedSet by aggregation, so that the public interface of the class does not include LinkedListHashMap
class LinkedHashSortedMapThing extends AbstractSet implemenents SortedSet
{
LinkedListHashMap map;
public int size() {
return map.size();
}
}
First, the code should declare the variable with the interface Set or SortedSet. But you can hide the implementation by Not inheriting from LinkedHashMap. Just implement the interface and delegate to a LinkedHashMap member.
If you need protected access to LinkedHashMap functionality, use a private inner class as the delegation member.
In Java, is it possible to declare a field/variable whose type is multiple interfaces? For example, I need to declare a Map that is also Serializable. I want to make sure the variable references a serializable map. The Map interface does not extend Serializable, but most of Map's implementations are Serializable.
I'm pretty sure the answer is no.
Follow up: I'm fully aware of creating a new interface that extends both Map and Serializable. This will not work as existing implementations (such as HashMap) do not implement my new interface.
You can do it with generics, but it's not pretty:
class MyClass<T,K,V extends Serializable & Map<K,V>> {
T myVar;
}
There is no need to declare the field/variable like that. Especially since it can only be tested runtime and not compile time. Create a setter and report an error should the passed Map not implement Serializable.
The answers recommending that you create your own interface are of course not very practical as they will actively prohibit sending in things that are Maps and Serializable but not your special interface.
It's possible to do this using some generics tricks:
public <T extends Map<?,?> & Serializable> void setMap(T map)
The above code uses generics to force you to pass a map which implements both interfaces. However, note that a consequence of this is that when you actually pass it the maps, they will probably need to be either marked as serializable or of a map type which is already serializable. It also is quite a bit more difficult to read. I would document that the map must be serializable and perform the test for it.
public interface MyMap extends Map, Serializable {
}
will define a new interface that is the union of Map and Serializable.
You obviously have to then provide a suitable implementation of this (e.g. MyMapImpl) and you can then provide variable references of the type MyMap (or Map, or Serializable, depending on the requirements).
To address your clarification, you can't retrofit behaviour (e.g. a serializable map). You have to have the interface and some appropriate implementation.
I voted up Brian's answer, but wanted to add a little higher-level thought..
If you look through the SDK, you'll find that they rarely (if ever) pass around actual collection objects.
The reason for that is that it's not a very good idea. Collections are extremely unprotected.
Most of the time you want to make a copy before passing it off and pass the copy so that any modifications to the collection won't change the environment for something else that's relying on it. Also, threading becomes a nightmare--even with a synchronized collection!
I've seen two solutions, one is to always extract an array and pass it. This is how the SDK does it.
The other is to ALWAYS wrap collections in a parent class (And I mean encapsulate, not extend). I've gotten into this habit and it's very worth while. It doesn't really cost anything because you don't duplicate all the collection methods anyway (actually you rarely duplicate any of them). In fact what you end up doing is moving "Utility" functionality from other classes distributed all over your code into the wrapper class, which is where it should have been in the first place.
Any method with a signature that matches "method(collection,...)" should almost certainly be a member method of that collection, as should any loops that iterate over the collection.
I just have to throw this out every now and then because it's one of those things I didn't get for a while (because nobody championed the concept). It always seems like it's going to have some drawback but having done this for a while and seeing the problems it solved and code it eliminated, I can't even imagine any possible drawbacks myself, it's just all good.
You can achieve this by making your own Interface, which extends the interfaces you want
public interface SerializableMap<K, V> extends Map<K, V>, Serializable {
}
In my case it worked just to declare the concrete type:
HashMap<String, String> mySerializableMap = new HashMap<>();
It allowed me to use the Map methods (like put) and pass the map to methods that required a Serializable, without casting. Not perfect when we’ve learned to program towards interfaces, but good enough for me in the situation I was in.
If you really insist: As has been noted, declaring a combined interface alone does not solve the problem since the concrete classes we already have do not implement our combined interface even when they do implement each of the two interfaces we combine. I use it as a first step on the way, though. For example:
public interface SerializableMap<K, V> extends Map<K, V>, Serializable {
// No new methods or anything
}
The next step is also declaring a new class:
public class SerilizableHashMap<K, V> extends HashMap<K, V> implements SerializableMap<K, V> {
private static final long serialVersionUID = 4302237185522279700L;
}
This class is declared to implement the combined interface and thus can be used wherever one of those types is required. It extends a class that already implements each of the interfaces separately, therefore there’s nothing more we need to do. And now we have got what you asked for. Example of use:
public static void main(String[] args) {
SerializableMap<String, String> myMap = new SerilizableHashMap<>();
// myMap works as a Map
myMap.put("colour1", "red");
myMap.put("colour2", "green");
// myMap works as a Serializable too
consumeSerializable(myMap);
}
public static void consumeSerializable(Serializable s) {
// So something with the Serializable
}
For most purposes I suggest that this is overkill, but now I have at least presented it as an option.
Link: What does it mean to “program to an interface”?
You can't really do it if you want to keep using the existing Map implementations.
An alternative would be to make a helper class, and add a method like this one:
public static Serializable serializableFromMap(Map<?, ?> map) {
if (map instanceof Serializable) {
return (Serializable)map;
}
throw new IllegalArgumentException("map wasn't serializable");
}
Nope, you'll pretty much need to cast.