Is it possible to make generic method signature implementing generic + interface? [duplicate] - java

This question already has answers here:
Why can't I use a type argument in a type parameter with multiple bounds?
(5 answers)
Closed 7 years ago.
Is it possible to use generics something like that in Java 1.7?
class Test<T> {
public <Z extends T & Serializable> void method(Z test) {
...
}
}
I would like my method to accept only objects of generic type which implements specific interface.

No, unfortunately it is not possible to use generic extends with a generic type and an interface. In fact, it is not even possible to use generic extends with multiple types. If you could, then you could do something like the following.
class Test<T, B extends Serializable> {
public <Z extends T & B> void method(Z test) {
...
}
}
This restriction against extending multiple types may be because of type erasure. At runtime the generics are removed and public <Z extends Serializable> simply becomes public Serializable. So what would <Z extends T & Serializable> be replaced with?

The most approximated form would be:
class Test<T extends Serializable>
{
public <Z extends T> void method(Z test)
{
}
}

Related

Generics in java at method level [duplicate]

This question already has answers here:
Why does this Java method appear to have two return types?
(3 answers)
Closed 6 months ago.
I am new to java. I am trying to debug a code and not able to understand one line.
public interface CommandDispatcher {
<T extends BaseCommand> void registerHandler(Class<T> type, CommandHandlerMethod<T> handler);
void send(BaseCommand command);
}
I know generics but not able to understand below line.
<T extends BaseCommand> void registerHandler(Class<T> type, CommandHandlerMethod<T>)
what is <T extends BaseCommand> before void also I am not ablr to understand Class<T>
Can somebody explain me to understand the above line. Consider BaseCommand is an interface.
<T extends BaseCommand> means at the calling side Type T can be BaseCommand OR derived from BaseCommand class/interface.
Class<T> type means the first argument should be the type of Class T.
class Command extends BaseCommand{
}
then you can call like this
registerHandle( Command.class, ...);
So that inside implementation one can create instance of Type Command.

Class Generics method definition [duplicate]

This question already has answers here:
How do I make the method return type generic?
(19 answers)
Closed 5 years ago.
Assuming that you have a lot of classes that extends the class Base.
class Base{}
class A extends Base[}
class B extends Base{}
class C extends Base{}
What must I write so that when I write a get method, I will get the class that I want?
public Base get(Class <? extends Base> clazz, final String key){
//not important.
}
I want the method to return Objects of class A, B, or C, depending on the input clazz.
public <T extends Base> T get(Class<T> clazz, final String key) {
}
is closer to what you need. Keep in mind that during method declared generic variables, to have more success you typically put the modifiers outside of the parameter list.

Java Generics Name type parameter without requiring it [duplicate]

This question already has answers here:
Extract Generic types from extended Generic
(2 answers)
Closed 6 years ago.
Suppose I have some class Edge<A, B> with subclasses that provide the parameterization, e.g class MyEdge extends Edge<MyNodeType, MyOtherNodeType>
I am currently declaring another class that uses Edges as so:
class EdgeHolder<E extends Edge<A, B>, A, B> {
A getFirstNode();
B getSecondNode();
}
and using it as such:
EdgeHolder<MyEdge, MyNodeType, MyOtherNodeType> var = ...
This feels awfully clunky, especially since MyNodeType and MyOtherNodeType are specified in MyEdge's definition.
I'd love to be able to name the parameters A and B in the definition of EdgeHolder because I need compile-time type-checking on its methods' return type, but I don't want to have to specify A and B when I declare variables of type EdgeHolder.
Is there a way to do this (or something like it)?
If not, why not?
There is no type alias in Java, but you can try use this approach.
class Edge<A, B> {
class MyEdgeHolder<E extends Edge<A, B>> extends EdgeHolder<E, A, B> {}
}
class MyEdge extends Edge<MyNodeType, MyOtherNodeType> {
class MyEdgeHolder extends Edge<MyNodeType, MyOtherNodeType>.MyEdgeHolder<MyEdge> {}
}
Use it like this:
MyEdge.MyEdgeHolder var;
Edge<?, ?>.MyEdgeHolder<?> var2 = var;
This approach is very limited, but may fit your specific scenario.
The best idea I could come to reduce typing yet preserve type checking at compile time:
class Edge<A, B> {
A src;
B dest;
}
class EdgeHolderBase<A, B, E extends Edge<A,B>> {
Edge<A,B> in_hold;
}
// explicit specialization of generics
class MyEdge
extends Edge<Integer, Long> {
}
class MyEdgeHolder
extends EdgeHolderBase<Integer, Long, MyEdge> {
// --- One off excessive typing -- ^
}

Intertwined java generic interfaces and classes

I have a very specific problem with java generics. The follwowing classes and interfaces have been predefined:
public interface IFirst<R, T> {...}
public abstract class AbstractFirst<T extends AbstractFirst, L extends IFirst<String, T>> {...}
public interface ISecond extends IFirst<String, AbstractSecond> {...}
public abstract class AbstractSecond extends AbstractFirst<AbstractSecond, ISecond> {...}
Now I've created a following repo definition which seems to be valid:
public abstract class AbstractRepo<T extends AbstractFirst<T, IFirst<String,T>>> {...}
But now that i want to extend it:
public class RepoFirst extends AbstractRepo<AbstractSecond> {...}
I get the following error:
Bound mismatch: The type AbstractSecond is not a valid substitute for the bounded parameter
<T extends AbstractFirst<T,IFirst<String,T>>> of the type AbstractRepo<T>
I cannot change the first four (at least not radically) beacuse they are too heavily ingrained with the rest of the application, but the second two are new and up for change if need be.
Also intrestingly it allows the following (with raw type warnings):
public class RepoFirst extends AbstractRepo {
...
#Override
AbstractFirst someAbstractMethod() {
return new AbstractSecond() {...};
}
...
}
But for code clarity I would like to implement it with clearly defining AbstractSecond as the generic type for Abstract Repo.
What am I missing?
Your AbstractRepo expects an instance of IFirst and not a subtype of IFirst. But your AbstractSecond is clearly not IFirst. (I mean it is, from a OO standpoint but for generics, List<Number> is not the same as List<Integer>). It's ISecond. It might work if you could change your AbstractRepo from IFirst to ? extends IFirst as you did for AbstractFirst.

Java Generic classes assignability [duplicate]

This question already has answers here:
Multiple wildcards on a generic methods makes Java compiler (and me!) very confused
(3 answers)
Closed 8 years ago.
I have the following classes:
public interface ModelObject {
}
public interface Resource {
}
public interface Transformer <F,T>{
}
public interface WrapperFactory {
Transformer<Resource, Wrap<? extends ModelObject>> createMapper();
}
public class Wrap<E extends ModelObject> {
}
public class AbstractBaseTransformer<F,T> implements Transformer<F,T> {
}
public class ConcreteModel implements ModelObject {
}
public class ConcreteTransformer extends AbstractBaseTransformer<Resource, Wrap<ConcreteModel>> {
}
public class ConcreteFactory implements WrapperFactory {
#Override
public Transformer<Resource, Wrap<? extends ModelObject>> createMapper() {
return new ConcreteTransformer();
}
}
The ConcreteFactory doesn't compile stating that ConcreteTransformer is incompatible with returned
Transformer<Resource, Wrap<? extends ModelObject>>
I can't see what's wrong here. ConcreteTransformer binds 1st parameter to Resource (same as expected) while binding 2nd parameter to:
Wrap<ConcreteModel>
which should bind to:
Wrap<? extends ModelObject>
as ConcreteModel implements it.
Here is a simpler version, to narrow down the issue:
interface ModelObject {}
class ConcreteModel implements ModelObject {}
class Wrap<E extends ModelObject> {}
class SomeGeneric<T> {}
class Simple {
public SomeGeneric<Wrap<? extends ModelObject>> m() {
return new SomeGeneric<Wrap<ConcreteModel>>();
}
}
does not compile either.
Your problem is that a SomeGeneric<Wrap<ConcreteModel>> is not a SomeGeneric<Wrap<? extends ModelObject>>.
Wrap<ConcreteModel> is a subtype of Wrap<? extends ModelObject>? Yes.
Transformer<Resource, Wrap<ConcreteModel>> is a subtype of Transformer<Resource, Wrap<? extends ModelObject>>? No.
It's the same as:
String is a subtype of Object? Yes.
List<String> is a subtype of List<Object>? No.
Basically, for parameterized types to be compatible, if the top-level parameter is not wildcard, then the parameters must match exactly. In your case, the top-level parameter is not wildcard, and the parameters don't match exactly.
What you probably wanted instead was
Transformer<Resource, ? extends Wrap<? extends ModelObject>>
A Wrap<ConcreteModel> can be assigned to a variable of type Wrap<? extends ModelObject>. But the matter here is more complex.
Assume you have a ArrayList<Wrap<? extends ModelObject>> list. When you have such a type, it means that you can add a Wrap<ConcreteModel> to the list, but it also means that you can add a Wrap<ModelObject> to it. In brief, it means you have a list, that can contain a Wrap of anything that can be cast to a ModelObject.
On the other side, having a ArrayList<Wrap<ConcreteModel>> list means you can only add Wrap<ConcreteModel>s to it, while a Wrap<ModelObject> cannot be added to it, because the list can only contain wrapped ConcreteModels, and a wrapped ModelObject is not a wrapped ConcreteModel nor it can be cast to be one.
This is exactly your case. You declared your createMapper() method to return a Transformer<Resource, Wrap<? extends ModelObject>>. This means that the second argument of the returned Transformer must be able to be any subclass of ModelObject, including ModelObject itself. On the contrary, you are trying to return a Transformer<Resource, Wrap<ConcreteModel>>.
The compiler needs to enforce this because Transformer<F, T> could declare a method:
void myMethod(F fObject, T tObject);
If that was the case, the method myMethod of an object of type Transformer<Resource, Wrap<? extends ModelObject>> would accept an object of type ModelObject as its second argument. On the other side, the same method, in a object of type Transformer<Resource, Wrap<ConcreteModel>> cannot accept a ModelObject as its second argument.

Categories

Resources