Generics : Specify that parameter must be an interface - java

I try to do a generic class like this :
public abstract class MyClass<A extends MyInterface,B,C> implements A{
...
}
(Note: B and C are not interfaces, just other generic params)
I get a compilation error because there is absolutely no guarantee that A is an interface. Hence, the abstract class cannot implements A
Is there a way to tell the compiler that A must be an interface?

No,
Since you are using clause which after compilation will have following form like:
public abstract class MyClass implements java.lang.Object {
You can add implements MyInterface, B, C since that would check whether these interfaces are implemented.

Related

How to override a method with generic type

I need to override a generic method like below:
interface Converter{
<S, T> T convert(S s);
}
Now I have Class A and Class B, I want to override above method by convert Class A object to Class B object. I did like below but all show error not implement the method. Is there a way I can specify the class A and Class B in the override method?
I tried below :
Class ConverterImpl implements Converter{
#Override
B convert(A a){
//...
}
}
I tried above, it has compile error says not implement convert method
I think what you want is generify the interface.
interface Converter<T,R> {
R convert(T toConvert);
}
and you implement it with
class AtoBConverter implements Converter<A,B> {
B convert(A toConvert);
}
With your method declaration, each class would need to implement the generic version.
BTW it is usually good practice to use existing interfaces; in this case, this would be Function<T,R> with the method R accept(T).

How to set a Common type for Callable

I want to implement a super class and it is a java.util.concurrent.Callable . The child class will return different types of objects for Callable. Therefore, I want set this super class callable's generic type as to be any type. Following is my super class declaration.
public abstract class AbsTaskRunner implements java.util.concurrent.Callable {
I want to set generic type of Callable as any type.
public abstract class AbsTaskRunner implements java.util.concurrent.Callable <HERE_COMMON_TYPE> {
You can try with:
public abstract class AbsTaskRunner<T> implements java.util.concurrent.Callable<T>
Then the sub-classes can be either generic (like this):
public class GenericSubclass<T> extends AbsTaskRunner<T>
or extend AbsTaskRunner for some specific type (like this):
public class StringSubclass extends AbsTaskRunner<String>

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.

Inherit generic type and force the <type>

Is it possible to inherit generic type and to force in the child class the type received?
Something like:
class A<GenericType>{}
class B extends A<GenericType>{}
Or:
class B <PreciseType> extends A <GenericType>{}
But where do I define the GenericType used in B?
Given
class A<T> {}
It depends on what you try to do, but both options are possible:
class B extends A<SomeType> {};
B bar = new B();
A<SomeType> foo = bar; //this is ok
and
class B<T> extends A<T>{}; //you could use a name different than T here if you want
B<SomeType> bar = new B<SomeType>();
A<SomeType> foo = bar; //this is ok too
But keep in mind that in the first case SomeType is an actual class (like String) and in the second case T is a generic type argument that needs to be instantiated when you declare/create objects of type B.
As a piece of advice: using generics in collections is easy and straightforward, but if you want to create your own generic classes you really need to understand them properly. There are a few important gotchas about their variance properties, so read the tutorial carefully and many times to master them.
Assuming A is declared as class A<T> {} and you want be to be specialised on String only for example, you can declare it as class B extends A<String>.
Example:
public class A<T> {
public T get() {
return someT;
}
}
public class B extends A<String> {
public String get() {
return "abcd";
}
}
class B extends A<GenericType>{}
This is possible. Your B class will be a new class that extends generic A class with specific class as parameter and B will not be a generic class.
class B <PreciseType> extends A <GenericType>{}
In this case you create a generic class B which has generic parameter PreciseType. This class B extends a specific version of A, but A's parameter doesn't depend on PreciseType.
If you want to create a generic class that has a parameter which is used in specification of parent class you can use the following:
class B <PreciseType> extends A <PreciseType>{}

Narrow a Java field type without making the enclosing class generic?

Is it possible to narrow the type of a field in a Java class without making the containing class itself generic?
The generic example would be something like this:
abstract class MyClass {
//...
}
interface MyInterface {
//...
}
class MyConcreteClass<T extends MyClass & MyInterface> {
private T value;
}
Is there any way to do the following:
class MyConcreteClass {
private MyClass & MyInterface value;
}
This is essentially equivalent to MyConcreteClass or the raw MyConcreteClass type. In my implementation the type parameter will vary over the lifetime of the object (cursed mutability! It is imposed upon me by JPA!) and so the type annotation seems somewhat superfluous.
EDIT -
There is an additional restriction I forgot to mention. We will also have this:
class SubA extends MyClass
class SubB extends MyClass
class SubC extends MyClass
class SubSubA extends SubA implements MyInterface
class SubSubB extends SubB implements MyInterface
class SubSubC extends SubC implements MyInterface
Thus, simply declaring an abstract subclass of MyClass that implements MyInterface is not a suitable solution.
Also, the ultimate field type must be a concrete type, rather than simply an interface representing the intersection, for the simple reason that JPA-persisted entites cannot be referenced by their interface types. That is, a persistent field in a JPA entity class must be of either a primitive type or a concrete entity type.
I have never come across a problem like that (and thus no elegant solution comes to mind :-)... however...
interface Fooable
{
}
abstract class MyClass
implements Fooable
{
}
interface MyInterface
extends Fooable
{
}
class MyConcreteClass
{
private Fooable value;
}
In such complicated cases you should hide classes behind interfaces.
Then you can define an explicit interface for the intersection, i.e. an interface that extends both the interface corresponding to MyClass and MyInterface, and letting the appropriate superclasses implement it instead of MyInterface.
I don't think there is a way to do that. Not exactly like that anyway. However, since this is a private field and you control it entirely, you can just declare it as
private MyClass value;
but also make sure in all your code that only objects that implements MyInterface are affected to it, and cast everywhere you need to access it as the interface. Yes, it looks dirty, and it is (slightly).
You could also create the following derived class
abstract class MyDerivedClass extends MyClass implements MyInterface {
//...
}
and then use
private MyDerivedClass value;
This is much cleaner, but you have to create an other class, just for that purpose...

Categories

Resources