Generic Type as generic type parameter - java

I want to know if I can improve my class, by avoiding the second V in the declaration of my class. Somehow it looks awful.
public abstract class TreeElementAction<T extends TreeNode<V>, V> {
protected abstract boolean actFor(#Nullable T element);
public void forEachElementInTree(#Nonnull T rootNode) {
requireNonNull(rootNode);
actFor(rootNode);
Collection<T> children = (Collection<T>) rootNode.getChildren();
for (T treeNode : children) {
forEachElementInTree(treeNode);
}
}
}

Unless you require V in any of the concrete implementations of this class, you can just drop the type variable, as #PeterLawrey has suggested, and replace it with an unbounded wildcard in TreeNode<V>:
public abstract class TreeElementAction<T extends TreeNode<?>> {

Related

Using self-referential generic types in Java

Consider the following Java method:
<T extends List<T>> List<T> getMyList() {
return Collections.emptyList();
}
I can assign its output to a variable with a raw type, like so:
List x = getMyList();
List<List> y = getMyList();
But, I can't think of any way to assign its output to a fully parameterized type. In particular, I can't think of a non-raw, concrete type T that would satisfy List<T> z = getMyList();
Can we create such a T ?
If not, why not?
For context, I created this question while trying to understand how Enums are implemented in Java.
Here's an example of a concrete type that both works and starts to hint at a possible use-case (registration of some sort). The type consists acts like both an instance of some type, and as a container for all instances of that type.
public class WeirdEnum extends AbstractList<WeirdEnum> {
private static List<WeirdEnum> underlyingList = new ArrayList<>();
#Override
public WeirdEnum get(int index) { return underlyingList.get(index); }
#Override
public int size() { return underlyingList.size(); }
static <T extends List<T>> List<T> getAList() {
return Collections.emptyList();
}
public WeirdEnum() {
underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
}
static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Not sure if I fully understand your question, but here's an example:
class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
Every enum in Java extends from the base-enum-class Enum<T extends Enum<T>>, where T is the actual type of the implementing enum.
When writing SomeClass<T extends SomeClass<T>> you can enforce that the type-parameter is always the implementing class itself.
Let's say you have this interface:
public interface MyInterface<T extends MyInterface<T>> {
T getSelf();
}
And this implementing class:
public class MyClass implements MyInterface<MyClass> {
public MyClass getSelf() {
return this;
}
}
In MyClass it is not possible to use any other type-parameter than MyClass itself.

Dependencies between generic classes

I have the following Interfaces:
public interface Assembler<T, S> {
S assemble( T val);
}
public interface Slicer<T, V> {
V[] slice(T val);
}
I want to have an Assembler instance use a Slicer instance and call it’s slice(). I have the following:
public class MyAssembler<T, S> implements Assembler<T, S> {
private final Slicer<T, V> slicer;
//ctor
public MyAssembler() {
slicer = new MySlicer<T, V>();
}
#Override
public S assemble(T val) {
V[] v = mySlicer.slice(val);
}
This doesn’t compile because the V type is not known (cannot be resolved to a type) in MyAssembler. I cannot change the Assembler interface to be Assembler<T, S, V>. Is there another way I can define the dependency? This is not an issue with non generic classes. Even if a static factory method is used to get the reference to Slicer, the problem of unknown V would still exist. Any suggestions? If this cannot be done, can anyone recommend a different approach or design pattern that allows for an Assembler to call the Slicer's slice()?
Will Assembler always have Slicer as one of its two generics? If so, you only need to define one generic, and have the Slicer as a non-generic member variable.
If, however, the generic types may or may not be Slicer, you can implement special handling for when one of them is Slicer with reflection, especially if (v instanceof Slicer) and then casting to Slicer if true.
Since your S and V are generic, you can exchange them for any other type, even other generics. You can do:
public class MyAssembler<T, S> implements Assembler<T, S> {
private final Slicer<T, S> slicer;
public MyAssembler() {
slicer = new MySlicer<T, S>();
}
#Override
public S assemble(T val) {
S[] v = slicer.slice(val);
return v[0]; // for example
}
}
What I did is to define T and S as the same type. In my own implementation, I can do this without problems.
Reposting Sotirios Delimanolis' comment as the answer.
To allow for the use of V in MyAssembler, declare MyAssembler<T, S, V> extends Assembler<T, S>. To use it, instantiate with for ex: Assembler<Integer, Integer> asmblr = new MyAssembler<Integer, Integer, Integer>.
Inheritance will solve your problem instead of Composition in this case as shown below:
public class MyAssembler<T,S,V> extends MySlicer<T,V> implements Assembler<T,S> {
public MyAssembler() {
}
#Override
public S assemble(T val) {
V[] v = this.slice(val);
...
}
}

Java: Specifying generic type restrictions in a subtype

I have a question regarding generic types in Java. Specifically, at present, I have some code similar to this:
public interface Foo {
public <T> void bar(T[] list)
}
public class FooImpl implements Foo{
#Override
public <T extends Comparable<? super T>> void bar(T[] list) {
...
}
}
The problem is, that the compiler now complaints, that I have not implemented the bar-method in my FooImpl class.
What I want is to put some extra restriction on the generic type, specifically that they should be comparable. But I don't want to put that restriction in my Foo interface, as all implementations does not need that restriction.
Is this possible, and what should I do to fix it?
Thanks a lot in advance!
EDIT 1: Fixed typos Class --> class and Interface --> interface. But the return types are still void, not T, which is irrelevant, I suppose. My actual return type is a boolean.
EDIT 2: The actual code, as requested:
public interface SortedCriteria {
public <E> boolean isSorted(E[] list);
}
public class AscendingCriteria implements SortedCriteria {
#Override
public <E extends Comparable<? super E>> boolean isSorted(E[] list) {
int length = list.length;
for (int i = 1; i < length; i++) {
if (list[i].compareTo(list[i-1]) < 0) return false;
}
return true;
}
}
What you want to do is rejected because it would completely break polymorphism. A caller having a Foo instance could have an instance of your subclass or an instance of any other subclass. And since the interface guarantees that the method can be called with any kind of array as argument, your subclass can't break this contract by limiting the kind of array it accepts (unless it does that at runtime, by checking the type of the array and by throwing an exception, of course).
This boils down to the Liskov substitution principle, which is the basis of polymorphism and OO.
But maybe what you actually want is to make Foo a generic type:
public interface Foo<T> {
public void bar(T[] list);
}
public class FooImpl<T extends Comparable<? super T>> implements Foo<T> {
#Override
public void bar(T[] list) {
...
}
}

How would one go about dealing with generic enums in Java?

So, I have an abstract class like:
public abstract class AbstractParent <E extends Enum<E>> {...}
Somewhere in a non-abstract method inside AbstractParent, I would like to iterate over the values of E. Is this possible?
For a better example:
public abstract class AbstractParent <E extends Enum<E>> {
...
protected void doSomething() {
//iterate over the values of E and perform an action using them
}
}
public class Child extends AbstractParent<Child.Index> {
public static enum Index {
...
}
public Child() {
super();
this.doSomething(); //this should iterate over Index's values
}
}
EDIT:
So, thanks to mdma, this works awesomely:
public abstract class AbstractParent <E extends Enum<E>> {
...
protected void doSomething() {
//iterate over the values of E and perform an action using them
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
Type t = pt.getActualTypeArguments()[0];
E[] enumValues = ((Class<E>)t).getEnumConstants();
// enumValues is now an iterable array of the values inside Index
}
}
public class Child extends AbstractParent<Child.Index> {
public static enum Index {
...
}
public Child() {
super();
this.doSomething(); //this should iterate over Index's values
}
}
Thanks LOADS to mdma, you deserve more points than I can give.
EDIT2: Generics on superclasses and interfaces are not erased. You can get the generic type at runtime and use that to fetch the enum values. See Class.getGenericSuperclass. This will save you having to pass the value or a class in the constructor.
Original:
You cannot do this with generics. However, if you pass in the corresponding class also, e.g. a constructor like
AbstractParent(Class<E> enumClass)
{
this.enumClass = enumClass;
}
Then you can use that to fetch the corresponding enum values via
public E[] getValues()
{
return this.enumClass.getEnumConstants();
}
EDIT: Although the clients are not professional programmers, the compiler will ensure the correct class is passed. You can also make the usage clear by providing examples, and unit tests.
You could also have the constructor take and actual value of the Enum, and derive the class from that. This might be simpler to use, since the parameter is then an E rather than the more "scary" Class<E>.
E.g.
AbstractParent(E enumValue)
{
this.enumClass = enumValue.getClass();
}
Since generics are erased at runtime, the only way this is possible is by having a constructor that requires a Class<E> parameter on which you can then call getEnumConstants().

Implementing a generic interface with a raw type

I have a generic tree, the generic parameter is the data type stored by the nodes:
class TreeNode<D>{
public D data;
.....
}
Then a visitor interface to use along with a tree transversal:
interface Visitor<D> {
void visit(TreeNode<D> node);
}
Some visitors can take advantage of generics:
class DataListCreator<D> implements Visitor<D> {
List<D> dataList = new ArrayList<D>();
public void visit(TreeNode<D> node) {
dataList.add(node.data);
}
public List<D> getDataList() {
return dataList;
}
But others don't, they would fit better in a raw class
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
But I don't know how implement this last case, the code above don't compile as I have to implement
the generic interface not the raw one. I tried implementing
Visitor<?>
with the same result. So my question is, I'm forced to use a generic type
NodeCounter<D>
to implement the Visitor interface?.
Thanks.
the code above don't compile
I tried compiling your example, and it works fine. I'm using Java 6. What was the compilation error you got?
This is what I successfully compiled:
class TreeNode<D>{
public D data;
}
interface Visitor<D> {
void visit(TreeNode<D> node);
}
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
}
Java generics are very powerful, and raw types should almost never be necessary.
You probably want to put some wildcards in. For instance, a visitor may need not know the exact generic argument of the TreeNodes it is visiting:
interface TreeNodeVisitor<D> {
void visit(TreeNode<? extends D> node);
}
Perhaps better(?), a TreeNode may not need to know the exact type of visitor.
interface TreeNode<D> {
void accept(TreeNodeVisitor<? super D> visitor);
}
In short - yes, you do need to give the generic interface a type argument.
What you probably should do, is implemenet a non-generic (and possibly empty) interface ITreeNode, that ITreeNode<D> inherits from. Any methods that don't need to be generic are declared in this intercace instead. Then, do the same thing for IVisitor, and NodeCounter can inherit the non-generic Visitor interface.
Short schematic:
ITreeNode
ITreeNode<D> implements TreeNode
IVisitor
IVisitor<D> implements IVisitor
NodeCounter implements IVisitor
(Note: I used the C# convention to prefix interfaces with I. NodeCounter is meant to be a class, while the others are interfaces...)
Java Generics are explicitly designed to be interoperable with raw types using a technique known as Erasure.
So the situation you are describing is directly supported and should compile fine:
class TreeNode<D>{
public D data;
}
interface Visitor<D> {
void visit(TreeNode<D> node);
}
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
}

Categories

Resources