First, I have a simple template, nothing fancy:
public abstract class ListOfK<K> {
private List<K> insides = new ArrayList<>();
}
Next, I'm creating a service interface using the template
public abstract interface SomeService<K extends ListOfK<K>> {
int calculateSomething (K input);
int calculateAnother (ListOfK<K> list);
}
So far so good with the abstraction.
Now, let's get to the implementation
public class ListOfString extends ListOfK<String> {
}
and implementation of SomeService:
public class SomeServiceImpl extends SomeService<String> {
#Override
public int calculateSomething(String input) {
return 0; // TODO impl
}
#Override
public int calculateAnother(ListOfK listOfK) {
return 0; // TODO impl
}
}
Somehow, when SomeServiceImpl extends SomeService<String>, it marks Type parameter java.lang.String is not within its bound; should extend ListOfK<String>
What should I input as implementation of SomeService so it doesn't give error? Or do I make mistake with SomeService? I just want a class whom input is a another class using Generic.
Thanks in advance.
The key insight here is that K in the context of the ListOfK class is not the same type as K in the context of the SomeService class. In fact, in your definition of SomeService, you're saying that K needs to itself be a ListOfK, which I suspect is your problem.
Does calculateSomething need to take (1) a single value, or (2) a ListOfK of values?
Does calculateAnother need to take (1) a ListOfK of values, or (2) a ListOfK of ListOfK values?
I think you want option 1, but you've actually chosen option 2.
To fix this, don't constrain K in SomeService:
public interface SomeService<K> {
int calculateSomething(K input);
int calculateAnother(ListOfK<K> list);
}
The issue lies in the way you are defining the SomeService interface. Your code of <K extends ListOfK<K>> says that "we need a class K which extends ListOfK, which uses K as its type parameter." So that class would have to look something like:
public class Test extends ListOfK<Test> {
Which doesn't make any sense. It shouldn't only use itself inside of the list. If you change the interface to something like:
public abstract interface SomeService<K extends ListOfK<?>> {
It should fix your issue.
Related
Consider the following code
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
public interface myInterface {
int doSomething();
}
public class myInterfaceImpl implements myInterface {
public int doSomething() {
return 1;
}
}
public void callDoSomething(Class<? extends myInterface> myVar) {
System.out.println(myVar.doSomething());
}
On this line callDoSomething(new myInterfaceImpl()); I get the following error.
Error:(32, 25) java: incompatible types: com.myProject.myTest.myInterfaceImpl
cannot be converted to java.lang.Class<? extends com.myProject.myTest.myInterface>
How do I satisfy the parameter type? If only an interface is provided to me.
I want to bound the class that has an interface, but it seems like this is not avaiable to me
Class<? implements myInterace>
Edit:
The reason I want to do this is because I want to provide a custom kafka partitioner.
public Builder<K, V> withCustomPartitionner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
It looks like you want to be able to call methods on the parameter that's given. In that case, you'll want the actual instance of your interface, not the Class associated with it.
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
Class<> is used when you want to use reflection to do something with the specific class type that you're interested in:
public void outputClassInfo(Class<? extends myInterface> myClass) {
System.out.println(myClass.getName());
}
If that's what you're going for, you'll want to provide the class at compile time like this:
outputClassInfo(myInterfaceImpl.class);
Or, if you won't know which class you're dealing with until runtime, you can use reflection:
myInterface thing = getThing();
outputClassInfo(thing.getClass());
So, in the example you're providing in your edit, I'm guessing you want:
public Builder<K, V> withCustomPartitioner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
// Usage
builder
.withCustomPartitioner(FooPartitioner.class)
...
This type Class<? extends myInterface> myVar corresponds to a Class instance not to an instance of myInterface.
You generally don't pass a class as parameter (but for reflection purposes or to bypass generics erasures). So what you need as parameter is probably :
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
That you could invoke :
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
The parameter to callDoSomething shouldn't be a class. It must be an instance of that class or it's subclass.
public <T extends myInterface> void callDoSomething(T myVar) {
System.out.println(myVar.doSomething());
}
On a side note, don't name Java classes/interfaces starting with lower case.
As rightly mentioned by Andy Turner#, there is no need to use a type parameter here and you can just refer to the type as myInterface
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
You need to pass the Class not an instance.
callDoSomething(MyInterfaceImpl.class);
I want to know if is it possible to set a paramenter's type that is the type of the class that implements a given interface. Seeing some code the question will become more clear:
interface A {
A sum (???? another);
}
class AClass implements A {
private int internalStuff;
A public sum (???? another) {
// I want to access another.internalStuff in a type safe fashion
}
}
Of course I can substitute ???? with A type, and inside AClass.sum, cast it to AClass but that is ugly. Can "????" be replaced with some meaningful type declaration?
There is no self-type in Java, so you have to do a little trick to achieve this.
You can add a type parameter with a recursive type bound to the interface. The implementing class sets this parameter to its own type. Like this:
interface A<T extends A<T>> {
A sum (T another);
}
class AClass implements A<AClass> {
private int internalStuff;
public A sum(AClass another) {
// ....
}
}
There is nothing stopping AClass from doing implements A<SomeOtherAClass> though. You have to trust the implementing class to provide the correct type parameter.
I have the following class hierarchy:
public abstract class Config<T> implements Proxy<T> {
public abstract T parse();
public T get() {....}
}
public class IntegerConfig<Integer> extends Config<Integer> {
public Integer parse() {...}
}
public class LongConfig<Long> extends Config<Long> {
public Long parse() {...}
}
public class IntegerListConfig<List<Integer>> extends Config<List<Integer>> {
public List<Integer> parse() {....}
}
And so on...
I'd like to introduce a new class:
public class ConfigMutation<T> implements Proxy<T> {
public ConfigMutation(....) {
//// create a concrete implementation of Config<T> according to actual parameterized type
}
}
Essentially, I'd like to avoid repeating the entire class hierarchy of Config, and support in ConfigMutation all types that have parameterized implementations in Config class hierarchy.
Couldn't find a way to do it. (Class<T>)((ParameterizedType)getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0] obviously returns T, and not the actual type.
Also, once this problem is solved, I'd be happy if someone could suggest some factory pattern with generic types, so when I'm instantiating a Config derived class inside ConfigMutation, I wouldn't have to do it with a huge if...else block on actual type.
Thanks,
Lior
Change your ConfigMutation class to :
public class ConfigMutation<U,T extends Config<U>> implements Proxy<U> {
public ConfigMutation() {
}
}
You can then use ConfigMutation as :
ConfigMutation<Integer,IntegerConfig> mutation;
You won't be able to do something as follows which is what you want :
ConfigMutation<String,IntegerConfig> mutation;
That said, there is a change you need to make to your concrete Config implementers as well. For example, change IntegerConfig to :
public class IntegerConfig extends Config<Integer> {
public Integer parse() {...}
}
The Integer in IntegerConfig<Integer> will be considered as a type parameter and not the Integer class which is not what you want. (An IDE should give you a warning for this; The type parameter Integer is hiding the type Integer)
Currently I have this setup:
public abstract class Manager<B extends Bean, C extends AbstractConstraint> {
public final int insert(B b);
public final boolean update(B b);
public final boolean delete(B b);
public final B get(C... c);
public final List<B> search(C... c);
public final List<B> getAll();
}
public interface Bean { }
public abstract class AbstractConstraint { }
concretely used in:
public class AccountManager extends Manager<AccountBean, AccountConstraint> { }
public class AccountBean implements Bean { }
public class AccountConstraint extends AbstractConstraint { }
A few remarks:
Bean is the lowest entity possible. This is the direct instance of a row from a table in the database.
A concrete implementation of AbstractConstraint should not implement/extend a concrete implementation of Bean, unless I am mistaken here.
Via the Manager I can be sure that all you can pass in is a concrete version of <Bean, AbstractConstraint>.
However currently it is entirely valid to define this:
public class BogusManager extends Manager<AccountBean, CharacterConstraint> { }
which makes no sense at all, how can I restrict the code such that this is not allowed anymore?
I think that I have two options:
1) Change AccountConstraint to AccountConstraint<AccountBean>, but I do not think that it would be valid since the type argument would not be used in AccountConstraint itself.
2) Have a way to define a relation R and let Manager check if <B, C> is in relation R, in other words you would need to check R(B, C). But you would also need to be able to define a relation R<AccountBean, AccountConstraint> then, which would mean that R = Manager, but I don't think that it could be true. Anyway, how would I be able to implement this if it would be true?
Regards.
Your first option is legal, you do not need to use type variable.
For the second option, you need to pass class instances of bean and constraint to manager constructor which will check if this is legal pair. As far as I know there is no way to implement such check in source only, i.e. add declarative constraint to source code.
Something like this should satisfy a compile-time version of option 2:
interface Witness< B, C > {}
public final class AccountConstraintsForAccountsOnly implements Witness< AccountBean, AccountConstraint > {}
public final class CharacterConstraintsForCharactersOnly implements Witness< CharacterBean, CharacterConstraint > {}
public abstract class Manager< B extends Bean, C extends AbstractConstraint, W extends Witness< B, C > { ... }
For Option 1
//add a Type
abstract class AbstractConstraint<T>{}
//Type is tied to your Concrete bean
abstract class Manager<B extends Bean, C extends AbstractConstraint<B> >
{
.
.
.
}
While implementing the Constraint, state what type of Constraint it is, by just passing the Bean Type
Ex.
class BogusBean implements Bean { }
class BogusConstraint extends AbstractConstraint<BogusBean> { }
class BogusManager extends Manager<BogusBean, BogusConstraint> {}
I have the following class :
public abstract class Step {
public abstract <S,T> S makeAStep(S currentResult, T element);
}
and I'm trying to Implement it so it will take two int's and return the sum of them , something like this :
public class sumOfInts extends Step {
public <Integer,Integer> Integer makeAStep(Integer currentResult, Integer element){
return currentResult + element;
}
}
but I get the following error :
The type sumOfInts must implement the inherited abstract method Step.makeAStep(S, T)
please help me (I need it for my programming languages course homework)
I asking very kindly to write me a code that does what I want to accomplish which wont
have any errors or warnings
thanks in front
public abstract class Step<S,T> {
public abstract S makeAStep(S currentResult, T element);
}
public class SumOfInts extends Step<Integer,Integer> {
// etc.
I agree with Jonathan's answer.
There is also another possibility, given below, that keeps the type parameters on the method itself.
It's only theory in this case, because the class and method names suggest that this has no meaning for this example.
So I change the names for my example:
public abstract class Step {
public abstract <S,T> String makeAStep(S first, T second);
}
public class ConcatTwo extends Step {
public <S, T> String makeAStep(S first, T second){
return String.valueOf(first) + String.valueOf(second);
}
}
Note : This works because the operation uses String.valueOf(Object), that works for any type (all subclass Object). For another operation, we would have to restrict S and T, using something like
S extend Integer for example.