I'm trying to design a special type of collection that may only contain elements of its own type. This collection class must also be extendable. At first glance, this seems like a simple enough task:
public class MyClass<E extends MyClass> implements Collection<E>{
//insert Collection<E> methods here...
}
However, because one of these collections may only contain elements that are instances of its class, the following shouldn't be possible:
public class MySubclass extends MyClass<MyClass>{}
What I need is a version of MyClass that essentially does the following (don't try to compile this one):
public class MyClass<E extends this.getClass()> implements Collection<E>{...}
Is it possible to implement something like this? If so, how can it be done?
I think the signature your are looking for would be something like this:
public class MyClass<E extends MyClass<E>> ...
The problem with this, and why I don't think you can enforce what you want from a declaration standpoint is that you have an infinite loop. If the collection may only contain elements of its own type, then elements can only contain elements of itself, etc, etc.
You now have an infinite loop where you may only contain Collections and at no point will you have a Collection that contains some THING.
Also, remember that at runtime type-erasure does away with all generic type. Therefore, no matter how fancy your generic declaration is at any point someone could do the following and just get a warning:
new MyClass();
That is another reason why trying to enforce this type of structure probably won't work well.
Instead you could put an appropriate check in the add method that would provide runtime enforcement. Still have the infinite loop issue though.
EDIT
To do runtime checking, do the following:
public boolean add(E element){
if (!(element instanceof MyClass))
throw new IllegalArgumentException("Element is not an instance of MyClass");
// rest of add code here
}
Related
I'm trying to learn how to use generics and for that, I'm creating my own data structure similar to a list with an Iterator and all.
The uppermost class is declared as:
public class BasicList<A> implements Iterable {
}
It's just a list with nodes and a single pointer to the next element.
There's another list, called DescendingList, that does pretty much the same, only this time around, you're getting another output since the Iterator is different. I'm giving a comparator to this List to get the Iterator to work. The comparator is just an interface:
public interface Bigger<A> {
boolean bigger(A x);
}
DescendingList looks like this:
public class DescendingList<A extends Bigger<A>> extends BasicList<A> implements Iterable {
}
The idea is that it could work with any kind of object that is comparable through the Bigger interface.
Now I have an abstract class:
public abstract class Rock implements Bigger<Rock> {
}
And finally, a normal class which extends the Rock class:
public class Mineral extends Rock {
}
So, the issue at hand is that, while I can easily create a new BasicList filled with Minerals like this:
BasicList<Mineral> min = new BasicList<Mineral>();
I can't do the same with the DescendingList. Whenever I try going with
DescendingList<Mineral> min = new DescendingList<Mineral>();
my IDE (IntelliJ) goes all
"Type parameter "Rock" is not within it's bound; should implement Bigger<Mineral>"
And I don't really get why that happens. I am pretty sure that I've messed up the type parameters somehow and I'm really not sure where. This should be solveable somehow (at least without removing any classes/interfaces - the class headers might be and probably are completely messed up). Thanks in advance for any help you might offer.
A Mineral isn't a Bigger<Mineral>, it's a Bigger<Rock>, and that is incompatible with Bigger<Mineral>, because even though a Mineral is a Rock, Java's generics are invariant. It needs to be a Bigger<Rock> because of how Rock is defined -- implementing Bigger<Rock> -- and that DescendingList declares type parameter A to be a Bigger<A>.
Because it's a consumer (type parameter as a method parameter), the type parameter A needs a lower-bound (super) on its declaration.
class DescendingList<A extends Bigger<? super A>> // ...
This way Mineral will be within its own bound.
As an aside, you are implementing the raw form of Iterable in BasicList; you should supply a type argument there.
I currently have an interface Ring that specifies methods like add, multiply, and so on. Thus, I can make a class of vectors whose elements are of type E that has an addition method, a dot product, etc. as long as E extends Ring. For example, a very simple class might look like
public class Vector<E extends Ring<E>> {
List<E> data;
public Vector() {
// constructor implementation here
}
public E dot(Vector<E> other) {
// initialize ``result" somehow
for (int index=0; index<data.size(); index++) {
result.add(data.get(index).multiply(other.get(index)));
}
return result;
}
}
In this simple example, one could simply initialize the result as data.get(0).multiply(other.get(0)) and then start the for loop at 1, but I'd like to know if there is a way to specify that there is a ``zero element" of type E.
Ideally, I'd like to specify that E has a static method called zero() so that the zero element is just E.zero(). I can't seem to figure out a way to do this. On the other hand, I can't just add a zero() method to the Ring interface because then I would have to do something like (new E()).zero(), and of course a generic constructor cannot be made in that way. There is a silly shortcut involving something like E zero = data.get(0).zero(), but this does not seem very nice and only works if I already have another instance of an element of type E floating around (which may not be the case in another context). So, is there any nice way to specify the existence of such a zero element that is guaranteed to be implemented in any class E that extends Ring?
You can't require implementing classes have a static method. I suggest you not reuse a common builtin class name like Vector as it leads to confusion.
If you have a non-trivial requirement for construction I suggest you use a Factory method to create your instance. In your case you can specify that E have a method zero() even though it is not static. The problem is you have to pass the class, or an instance of that class as an argument. A method/constructor doesn't know what generics you used when you called it and they have to be parameters.
I have some problem with generics, let me explain.
I have a class which wraps a LinkedList:
public class IdnList<T extends Numerable> extends IdnElement implements List<T> {
private LinkedList<T> linkedList;
#Override
public boolean add(T e){
return linkedList.add(e);
}
//stuff
}
please note that the generic type T of this class extends the Numerable interface.
Ok, now inside a different class I want to invoke this method as follows:
if(childToAdd instanceof Numerable)
((IdnList<?>)this).add((Numerable)childToAdd);
but eclipse says: The method add(capture#1-of ?) in the type IdnList<capture#1-of ?> is not applicable for the arguments (Numerable), and I really can't figure out why it can't work. Why can't I add a Numerable object to my list?
What am I missing?
EDIT:
it's a classic. You ask, and then you find a clue. It seems a workaround is:
((IdnList<Numerable>)this).add((Numerable)childToAdd);
but I don't know how elegant it is. I really appreciate further comments.
Say you have classes A and B that both extend Numerable. Then there are three valid types of IdnList: IdnList<A>, IdnList<B>, and IdnList<Numerable>.
I hope you would agree that you shouldn't be able to add any Numerable to an IdnList<A>.
Now, in this line of code, how does the compiler know whether you've matched up the types correctly?
(IdnList<?>)this).add((Numerable)childToAdd);
All it knows is that childToAdd is a Numerable, and that this is some kind of IdnList. It doesn't know what kind, so it can't guarantee type safety. Remember that generic type checking is done entirely at compile time, not runtime.
I see how the workaround allows the code to compile, but I'm not sure what the risks of it are. It seems to me that since the generic type parameters are erased at runtime, essentially you're just bypassing all type checking here.
The problem lies in the reference to the instance of the IdnList in your other class.
I cannot see it in your code example, but it appears that it does not have the proper type associated with it, especially not when it is being cast to a wildcard.
Since the IdnList requires a type (T) set per instance, there is no way for the compiler to know what you are trying to do.
If your reference to your IdnList has the proper type associated with it, it will accept any subclass of T, like so:
IdnList<Numerable> list = new IdnList<Numerable>();
list.add(new Numerable());
list.add(new AnotherType());
list.add(new YetAnotherType());
(Given that AnotherType and YetAnotherType are subclasses of Numerable)
Since you do not have any type set on the reference to your instance, I am guessing that what you are actually trying to do is this:
public class IdnList extends IdnElement implements List<Numerable> {
private LinkedList<Numerable> linkedList;
#Override
public boolean add(Numerable e) {
return linkedList.add(e);
}
}
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 question already has answers here:
Closed 12 years ago.
Possible Duplicate:
java Enum definition
Better formulated question, that is not considered a duplicate:
What would be different in Java if Enum declaration didn't have the recursive part
if language designers were to use simply Enum<E extends Enum> how would that affect the language?
The only difference now would be that someone coud write
A extends Enum<B>
but since it is not allowed in java to extend enums that would be still illegal.
I was also thinking about someone supplying jvm a bytecode that defines smth as extending an enum - but generics can't affect that as they all are erased.
So what is the whole point of such declaration?
Thank you!
Edit
for simplicity let's look at an example:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
what's wrong with this class structure? What can be done that "MyEnum<E extends MyEnum<E>>" would restrict?
This is a common question, and understandably so. Have a look at this part of the generics FAQ for the answer (and actually, read as much of the whole document as you feel comfortable with, it's rather well done and informative).
The short answer is that it forces the class to be parameterized on itself; this is required for superclasses to define methods, using the generic parameter, that work transparently ("natively", if you will) with their subclasses.
Edit: As a (non-)example for instance, consider the clone() method on Object. Currently, it's defined to return a value of type Object. Thanks to covariant return types, specific subclasses can (and often do) define that they return a more specific class, but this cannot be enforced and hence cannot be inferred for an arbitrary class.
Now, if Object were defined like Enum, i.e. Object<T extends Object<T>> then you'd have to define all classes as something like public class MyFoo<MyFoo>. Consequently, clone() could be declared to return a type of T and you can ensure at compile time that the returned value is always exactly the same class as the object itself (not even subclasses would match the parameters).
Now in this case, Object isn't parameterized like this because it would be extremely annoying to have this baggage on all classes when 99% of them aren't going to utilise it at all. But for some class hierarchies it can be very useful - I've used a similar technique myself before with types of abstract, recursive expression parsers with several implementations. This construct made it possible to write code that was "obvious" without having to cast everywhere, or copy-and-paste just to change concrete class definitions.
Edit 2 (To actually answer your question!):
If Enum was defined as Enum<E extends Enum>, then as you rightly say, someone could define a class as A extends Enum<B>. This defeats the point of the generic construct, which is to ensure that the generic parameter is always the exact type of the class in question. Giving a concrete example, Enum declares its compareTo method as
public final int compareTo(E o)
In this case, since you defined A to extend Enum<B>, instances of A could only be compared against instances of B (whatever B is), which is almost certainly not very useful. With the additional construct, you know that any class that extends Enum is comparable only against itself. And hence you can provide method implementations in the superclass that remain useful, and specific, in all subclasses.
(Without this recursive generics trick, the only other option would be to define compareTo as public final int compareTo(Enum o). This is not really the same thing, as then one could compare a java.math.RoundingMode against a java.lang.Thread.State without the compiler complaining, which again isn't very useful.)
OK, let's get away from Enum itself as we appear to be getting hung up on it. Instead, here is an abstract class:
public abstract class Manipulator<T extends Manipulator<T>>
{
/**
* This method actually does the work, whatever that is
*/
public abstract void manipulate(DomainObject o);
/**
* This creates a child that can be used for divide and conquer-y stuff
*/
public T createChild()
{
// Some really useful implementation here based on
// state contained in this class
}
}
We are going to have several concrete implementations of this - SaveToDatabaseManipulator, SpellCheckingManipulator, whatever. Additionally we also want to let people define their own, as this is a super-useful class. ;-)
Now - you will notice that we're using the recursive generic definition, and then returning T from the createChild method. This means that:
1) We know and the compiler knows that if I call:
SpellCheckingManipulator obj = ...; // We have a reference somehow
return obj.createChild();
then the returned value is definitely a SpellCheckingManipulator, even though it's using the definition from the superclass. The recursive generics here allow the compiler to know what is obvious to us, so you don't have to keep casting the return values (like you often have to do with clone(), for example).
2) Notice that I didn't declare the method final, since perhaps some specific subclasses will want to override it with a more suitable version for themselves. The generics definition means that regardless of who create a new class or how it is defined, we can still assert that the return from e.g. BrandNewSloppilyCodedManipulator.createChild() will still be an instance of BrandNewSloppilyCodedManipulator. If a careless developer tries to define it to return just Manipulator, the compiler won't let them. And if they try to define the class as BrandNewSloppilyCodedManipulator<SpellCheckingManipulator>, it won't let them either.
Basically, the conclusion is that this trick is useful when you want to provide some functionality in a superclass that somehow gets more specific in subclasses. By declaring the superclass like this, you are locking down the generic parameter for any subclasses to be the subclass itself. This is why you can write a generic compareTo or createChild method in the superclass and prevent it from becoming overly vague when you're dealing with specific subclasses.