Reputation: 63
Suppose I have a class called NodeList
with two fields, called value
(type Object
) and index
(type int
). NodeList
implements an interface called Copiable
, with a single method called copyNotSyncronized()
.
I want the NodeList
version of copyNotSincronyzed()
to recognize if this.value
implements Copiable
and, if that happens:
copyNotSincronyzed()
on this.value
and...NodeList
object that have this.value.copyNotSincronyzed()
as field value
.I tried to write the code and drown in red underlining. After that I know two things: my Eclipse really hate me and I still have to undestand how to use generics in Java.
What mistakes did I do?
public class NodeList implements Copiable {
int index;
Object value;
public NodeList(Object value, int index){
[...]
}
NodeList copyNotSincronyzed(){
NodeList copied;
if( onArray.findPositionsOfElement(this.value.getClass().getInterfaces() , this.getClass().getInterfaces()[0])[0] !=-1 )
// aka if this.value implements the same interface of this class (aka Copiable)
{
// Following line features three errors:
// Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <T, Copiable>
// T cannot be resolved to a type
// Syntax error on token "implements", , expected
Class<T implements Copiable> copiedObject = this.value;
copiedObject=copiedObject.copyNotSincronyzed();
copied = new NodeList( copiedObject , this.index );
}
else copied = new NodeList(this.value, this.index);
}
}
Upvotes: 0
Views: 133
Reputation: 9543
Java has an interface Clonable
that lets you clone unlinked (unsynchronized) objects through a method Object clone()
. There is a lot of controversy around this and the bottomline is that it's discouraged.
A widely accepted way of creating copies of objects is by using a copy-constructor. This will not work for general Object
since you don't know the run-time class in advance. In this case Clonable
-like structure may still prove useful.
Because Clonable
is legacy, it doesn't have generics. Let's make Copyable
as a replacement for Clonable
(and rename clone()
as copyNotSyncronyzed()
)
public interface Copyable<T> {
T copyNotSyncronyzed();
}
public class NodeList implements Copyable<NodeList> {
private int index; // make final too unless you plan to change it at some point
private Object value; // make final too unless you plan to change it at some point
public NodeList(final Object value, final int index) {
this.value = value;
this.index = index;
}
@Override
public NodeList copyNotSyncronyzed() {
if (value instanceof Copyable) {
Object copiedObject = ((Copyable<?>)this.value).copyNotSyncronyzed();
return new NodeList(copiedObject, this.index);
} else
return new NodeList(this.value, this.index);
}
}
The last question is if you are really happy with this structure, as it copies linked value
instances if they are not Copyable
. This can potentially create dangerous situations since code calling copyNotSyncronyzed()
may expect it to be comppletely unrelated to the original.
For example, if value is an int[]
. You create a copy using copyNotSyncronyzed()
, then you change some values in the array, and lo and behold, the values in the array of the original object are changed too.
Upvotes: 0
Reputation: 34628
An interface is a type, like a class. Therefore, when another class implements it, any object of that class can be used polymorphically as that interface.
Which means that you can check if that object implements that interface simply by using x instanceof Y
. It's an operator that tells you whether x "is a" Y, and Y can be either a class or an interface.
Once you established that your object implements the type, you can cast it into the type of the interface using parentheses.
For the code itself I refer you to the answer given by Vitaliy.
Upvotes: 0
Reputation: 8206
this.value is of type Object
. And you are trying to put it into a type Class<T implements Copiable>
. The compiler does not know how to do that so you are getting a compilation error.
In order to make this check you should use the instanceof operator, combine with a cast, like this:
if (this.value instanceof Copiable){ // check that the instance implements an interface
Copiable asCopiable = (Copiable)this.value; // safely cast to the appropriate type
}
Note that your problem does not have anything to do with generics.
Upvotes: 2