I am trying to implement a class representing an XML tree as follows:
public class XML<T extends XML<T>> {
private final List<MarkupLanguage> nodeList = new ArrayList<>();
private final Map<String, String> attributeList = new HashMap<>();
public T attr(final String key, final String value) {
if (value != null) {
this.attributeList.put(key, value);
}
return (T) this;
}
public T appendTo(final T node) {
node.add(this);
return (T) this;
}
...
}
My problem is typing of these clauses – I am getting unchecked cast for “return (T) this;”
and also when I try to use the XML class by itself:
final XML url = new XML("url");
new XML("loc")
.add("http://goout.cz")
.appendTo(url);
I am getting:
Unchecked cast to call appendTo(T) as a member of raw type XML.
How can I improve my code to get better typing?
What about the approach below (simple inheritance plus generic methods):
Note that the generic methods allow to get a node from one type T and return the instance’s type R, which can be different than the argument’s type. T can be different than R, but both inherit XML.
Comments about the approach presented in the question
The approach that you’re using until now can lead to strange situtations.
Let’s illustrate this with an example.
Below, we try to write the first class that specializes XML:
If we’re writing the first XML subclass, the only possible values to OtherXMLSubclass is XMLFirstSubclass or not declaring the generic type at all.
First option:
Second:
If you chose to use generics in your class design, the second option seems bad.
Taking a closer look into the first option, it opens the possibility of getting subclasses like:
Note that this compiles perfectly, but will cause class cast exceptions in XMLSecondSubclass method calls at runtime.