Generic type subclass - java

I have the following generic class:
public class Evalutor<T>{
}
I would like to create the type called NumberEvalutor as follows:
public class NumberEvalutor<T> extends Evalutor<T extends Number>{ //Syntax error on token "extends", , expected
}
But I couldn't do it that way. Maybe you can advice another type-safe way?

Try with:
public class NumberEvalutor<T extends Number> extends Evalutor<T> {
}
Type parameters on class-level (like <T extends Number>) must be introduced after the class name and can be referred in the super-class/super-interface list. Otherwise, there won't be a way to (explicitly) specify their runtime value when creating class instances.

This one should work :)
public class NumberEvaluator<T extends Number> extends Evaluator<T> {
}

Related

In an interface, I first declare a generic that extends an interface, then a generic that extends the first generic along with another interface

For example,
public interface Foo<T extends Blackness, S extends T & Whiteness> { }
Error: Type parameter cannot be followed by other bounds
T extends Blackness and S extends T so S inherently extends Blackness. The only other contingency is that S must also extends Whiteness. Because of this restriction, S must be an extension of T but also implement the functionality of Whiteness. Because of this, you will likely have to provide the type T. It's not possible for S to have multiple bounded types, which is why a sub-interface is required that implements both. What you're trying to do doesn't make logical sense. Refer to this.
public interface Foo<T extends Blackness, S extends BlackAndWhiteness<T>> {
}
public interface BlackAndWhiteness<T extends Blackness> extends Whiteness, Blackness {
}
interface Blackness {
}
interface Whiteness {
}

Java Generics: Class that takes a class that takes another class

I have a class BatchConfigurable
public class BatchConfigurable<T extends BatchContext>() {}
I am trying to write a wrapper for it. This will be another class that takes this class or any class that extends BatchConfigurable as parameter. For the declaration, I'm trying:
public class WrappedBatchConfigurable<E extends BatchConfigurable <T extends BatchContext>>() {}
This is invalid but as should be clear from the code, I want to preserve the property that the subtype of BatchConfigurable that WrappedBatchConfigurable takes should take a type that extends BatchContext as parameter. What would the syntax for this be?
You need to declare your type parameter T before you use it.
class WrappedBatchConfigurable<T extends BatchContext, E extends BatchConfigurable<T>> {}

composition of generic types in java

Let's say I'm defining a class User, which has a generic type which extends Principal
public abstract class User<P extends Principal> {
}
And I have an action base class which should be parameterized with an user:
public abstract class Action<U extends User<Principal>> {
}
Those two classes are on muy codebase. Now, I want to use them on an specific application, so I create an implementation for Principal and User:
public class MyPrincipal implements Principal {
public String getName() {
return "Administrator";
}
}
public class MyUser extends User<MyPrincipal>{
}
Once I have my user, I want to use it on an action
public class MyAction extends Action<MyUser>{
}
This last class does not compile. It complais that :
Bound mismatch: The type MyUser is not a valid substitute for the bounded parameter <U extends User<Principal>> of the type Action<U>
What I want is to enforce that all classes extending MyAction should be parameterized with an object that extends User, and also is parameterized by an object which implements Principal. What I'm missing?
Currently, the bound on your Action class says - U extends User<Principal>. Since MyUser deoesn't extend a User<Principal>, but a User<MyPrincipal>, it won't work as you expected. A User<MyPrincipal> is not a User<Principal> (distinct types).
You can introduce another type parameter in your Action class, and use that in bounds of U:
public abstract class Action<P extends Principal, U extends User<P>> {
}
and now, you can create your MyAction like this:
public class MyAction extends Action<MyPrincipal, MyUser>{
}
Or you can also modify your class using wildcard bound:
public abstract class Action<U extends User<? extends Principal>> {
}
This way you won't need another type parameter:
public class MyAction extends Action<MyUser>{
}
References:
Java Generics FAQs
Can I use a type parameter as part of its own bounds?
Change Action's signature to this (I tested this in Eclipse and it compiles):
public abstract class Action<U extends User<? extends Principal>>
By doing this, you're saying that any type of Principal is okay, not just base-type Principal objects (which of course can't be instantiated).

How to extend a generic class with added constraints in java?

I want to extend my BinaryTree class so that only Integer parameters are accepted and I can reuse the code.
public class BinaryTree<T extends Comparable<T>>
{/*code omitted for convenience*/}
public class BinaryTreeInt<T extends Integer> extends BinaryTree<T>
{/*code omitted for convenience*/}
I get following error on compilation-
BinaryTreeInt.java:1: type parameter T is not within its bound
public class BinaryTreeInt<T extends Integer> extends BinaryTree<T>
^
1 error
Can someone guide how to write code for such inheritance?
Integer is final so what you have is
public class BinaryTreeInt extends BinaryTree<Integer>
However the type implies its is int rather than Integer
The problem stems from the following potential class:
class FunnyNumber extends Integer { }
This class does not extend Comparable<T>, so it can't be used as the base T.
In other words, extends Comparable<Integer> is not the same as extends Comparable<T>.
Your second class should not be generic at all.
You should only use generics if you want to vary the type parameter.
Here, you want a single fixed type, so you should make a normal non-generic class that extends BinaryTree<Integer>. (or just use BinaryTree<Integer> directly and don't make a separate class at all)

Bounded Java Generics not compiling

I am unable to get this to compile and I don't see the reason why.
Ultimately I want to pass an Collection of objects who's class extends TClass into the generate method that takes a Collection of objects who's class extends TClass,
This should work.
Any help would be appreciated.
public interface Generator<IT extends ITClass, T extends TClass> {
IT generate(Collection<T> tClassCollection)
}
Generator<?, ? extends TClass> generator = generatorClass.newInstance();
Collection<? extends TClass> TClassCollection = ...
... generator.generate(TClassCollection);
I get this error
The method generate(Collection<capture#8-of ? extends TClass>) in the type
Generator<capture#7-of ?,capture#8-of ? extends TClass> is not applicable for the arguments (Collection<capture#9-of ? extends TClass>)
This should work
No; it would open a loophole in the type system if it did. Consider:
class SpecialT extends TClass {}
class SpecialGenerator extends Generator<ITClass, SpecialT> {}
Generator<?, ? extends TClass> generator = SpecialGenerator.class.newInstance();
Collection<? extends TClass> TClassCollection = Arrays.asList(new TClass());
generator.generate(TClassCollection);
A SpecialGenerator can only work with a Collection<SpecialT>, but you are trying to pass a Collection<TClass>, which can contain instances of types other than SpecialT.
A wildcard in a generic declaration doesn't mean "any type"; it means "some particular unknown type."
So, if you have a Generator<?, ? extends TClass>, it doesn't mean you can pass its generate() method any Collection as long as it contains a subtype of TClass.
On the contrary, it means that you can't invoke its generate() method in a type-safe way, because you don't know the type of elements it is capable of accepting.

Categories