Java generics - incompatible types - java

Just need some help with this error in code:
interface ParticleId{
int getX();
}
class ParticleId1 implements ParticleId{
int a;
#Override
public int getX() {
return a;
}
}
class ParticleId2 implements ParticleId{
int a,b;
#Override
public int getX() {
return a+b;
}
}
interface ParticleInt<K extends ParticleId, O extends ParticleInt<K, O>>{
O withSmt();
}
class Particle<K extends ParticleId> implements ParticleInt<K, Particle<K>>{
#Override
public Particle<K> withSmt() {
return new Particle<>();
}
}
class Particle2<K extends ParticleId> extends Particle<K>{
#Override
public Particle2<K> withSmt() {
return new Particle2<>();
}
}
interface Executable<P extends Particle<? extends ParticleId>>{
void setExecutableStrategy(ExecutableStrategy<P> s);
}
interface ExecutableStrategy<P extends Particle<? extends ParticleId>>{
Stream<P> exec(List<P> l);
}
class Particle2Strat implements ExecutableStrategy<Particle2<? extends ParticleId>>{
#Override
public Stream<Particle2<? extends ParticleId>> exec(List<Particle2<? extends ParticleId>> l) {
return l.stream().map(x -> x.withSmt());
}
}
class ParticleStrat<P extends Particle<? extends ParticleId>> implements ExecutableStrategy<P>{
#Override
public Stream<P> exec(List<P> l) {
return l.stream().map(x -> x.withSmt());
// [44,38] incompatible types: inference variable R has incompatible bounds
// equality constraints: P
// [ERROR] lower bounds: Particle<capture#1 of ? extends ParticleId>
}
}
The error is shown on the end of the code, and exact description is [44,38] incompatible types: inference variable R has incompatible bounds. equality constraints: P. [ERROR] lower bounds: Particle<capture#1 of ? extends ParticleId>.
Quick fix that I found working is just manually casting lambda to (P) like (P)x.withSmt(). Anybody knows more proper way to fix this if possible at all?
I just updated the code so it is not using anymore Integer but ParticleId interface.
UPDATE
After update I now have this problem:
class ParticleStrat<P extends ParticleId> implements ExecutableStrategy<Particle<P>>{
#Override
public Stream<Particle<P>> exec(List<Particle<P>> l) {
return l.stream().map(x -> x.withSmt()); //OK NOW
}
}
class MainExecutable<P extends Particle<? extends ParticleId>> implements Executable<P>{
private ExecutableStrategy<P> s;
public MainExecutable() {
this.s = new ParticleStrat<>();
//incompatible types: cannot infer type arguments for ParticleStrat<>
//no instance(s) of type variable(s) P exist so that ParticleStrat<P> conforms to ExecutableStrategy<P>
}
#Override
public void setExecutableStrategy(ExecutableStrategy<P> s) {
this.s = s;
}
}

Changing the declaration of ParticleStrat class to the following solves the compilation error:
class ParticleStrat<P extends ParticleInt<P>> implements ExecutableStrategy<P>{
#Override
public Stream<P> exec(List<P> l) {
return l.stream().map(x -> x.withSmt());
}
}
This way x.withSmt() is guaranteed to return P.
EDIT following the change in your question:
This passes compilation:
class ParticleStrat<K extends Integer> implements ExecutableStrategy<Particle<K>>{
#Override
public Stream<Particle<K>> exec(List<Particle<K>> l) {
return l.stream().map(x -> x.withSmt());
}
}
And after your latest update:
class ParticleStrat<K extends ParticleId> implements ExecutableStrategy<Particle<K>>{
#Override
public Stream<Particle<K>> exec(List<Particle<K>> l) {
return l.stream().map(x -> x.withSmt());
}
}
As for your latest problem, the same approach can work:
class MainExecutable<K extends ParticleId> implements Executable<Particle<K>>{
private ExecutableStrategy<Particle<K>> s;
public MainExecutable() {
this.s = new ParticleStrat<>();
}
#Override
public void setExecutableStrategy(ExecutableStrategy<Particle<K>> s) {
this.s = s;
}
}

Related

Is there a way to use a generic argument's own generic argument in Java?

I have this interface, with two generic parameters, and a Descriptor<T> class:
public interface DescriptorFinder<D extends Descriptor<T>, T> {
D find(Class<? extends T> describedClass);
}
public abstract class Descriptor<T> {
private final Class<? extends T> describedClass;
public Descriptor(Class<? extends T> describedClass) {
this.describedClass = describedClass;
}
public Class<? extends T> getDescribedClass() {
return describedClass;
}
}
Using those foundations I can create an NumberDescriptor to describe a number:
public class NumberDescriptor extends Descriptor<Number> {
private boolean handlesDecimalPart;
public NumberDescriptor(Class<? extends Number> describedClass) {
super(describedClass);
}
public boolean handlesDecimalPart() {
return handlesDecimalPart;
}
public void setHandlesDecimalPart(boolean handlesDecimalPart) {
this.handlesDecimalPart = handlesDecimalPart;
}
}
And then have a DescriptorFinder for it:
public class NumberDescriptorFinder implements DescriptorFinder<NumberDescriptor, Number> {
#Override
public NumberDescriptor find(Class<? extends Number> describedClass) {
NumberDescriptor descriptor = new NumberDescriptor(describedClass);
if (describedClass == Double.class || describedClass == Float.class) {
descriptor.setHandlesDecimalPart(true);
}
return descriptor;
}
}
Well, that DescriptorFinder<NumberDescriptor, Number> is pretty weird to use, I would like to remove the second generic parameter and reduce it to DescriptorFinder<NumberDescriptor>. So I tried something like this:
public interface DescriptorFinder<D extends Descriptor<?>> {
D find(Class<? extends T> describedClass); // How to get T?
}
But I couldn't find a way to get D's T argument, for example, if I had D as Descriptor<Number>, I want to get Number so I can have Class<? extends Number>.

How get Instance using Generic approach

I am trying to build one page assembler using generic approach. Following is piece of code.
In this code IEntity is marker interface for DB entities.
public abstract class PageHrefBuilder implements HrefBuilder<IEntity, PageLinks> {
#Override
public PageLinks buildLinks(IEntity entity) {
return null;
}
}
public interface HrefBuilder<E extends IEntity, L extends Links> {
public L buildLinks(E dto);
}
So we have one interface says can build links using IEntity type of class and return Links type of value. So I want to write some common code in abstract class and abstract class does not know what type entity it suppose to deal with.
For example entity can UserEntity, OrderEntity and so on.
So my question is how in abstract class I can get the class instance to build links with using instanceof or if else approach.
Could someone help me on this.
You can make your buildLinks method to take Class<T> parameter instead of the object you have to pass.
so it will be
public L buildLinks(Class<E> dto);
then in your abstract class
#Override
public PageLinks buildLinks(Class<IEntity> dto) {
return dto.newInstance();
}
Hope this answer could help you.
This got a bit over-engineered but it works and all generics are proper. Hopefully it shows you how you can build your solution:
public class GenericsSample {
public abstract class Links {
String data;
public Links(String data) {
this.data = data;
}
}
public class UserLinks extends Links {
public UserLinks(String data) {
super(data);
}
}
public class PageLinks extends Links {
public PageLinks(String data) {
super(data);
}
}
public abstract class IEntity<L extends Links> {
public abstract L buildLinks();
}
public class UserEntity extends IEntity<UserLinks> {
#Override
public UserLinks buildLinks() {
return new UserLinks("From UserEntity");
}
}
public class PageEntity extends IEntity<PageLinks> {
#Override
public PageLinks buildLinks() {
return new PageLinks("From PageEntity");
}
}
public interface HrefBuilderInterface<E extends IEntity<L>, L extends Links> {
public L buildLinks(E dto);
}
public class HrefBuilder<E extends IEntity<L>, L extends Links> implements HrefBuilderInterface<E, L> {
#Override
public L buildLinks(E entity) {
return entity.buildLinks();
}
}
public static void main(String[] args) {
new GenericsSample().go();
}
private void go() {
System.out.println(new HrefBuilder<UserEntity, UserLinks>().buildLinks(new UserEntity()).data);
System.out.println(new HrefBuilder<PageEntity, PageLinks>().buildLinks(new PageEntity()).data);
}
}
Also note that thanks to this setup the following is not valid:
System.out.println(new HrefBuilder<PageEntity, PageLinks>().buildLinks(new UserEntity()).data);
You can declare abstract method in abstract class to get new instance of Links interface:
abstract class PageHrefBuilder<E extends IEntity, L extends Links> implements HrefBuilder<E, L> {
#Override
public L buildLinks(E dto) {
L links = newLinks();
// ...
return links;
}
protected abstract L newLinks();
}
and implement getting new instance in realization.

Two classes implementing interface with different type arguments

class SingleTon{
Data<A> a;
Data<B> b;
Data<C> c;
// ... etc
class Data<O extends I<O>>{
O o;
public void update(O o){
this.o.update(o);
}
}
}
interface I<T>{
void update(T t);
}
class A implements I<A>{
private String a;
#Override
public void update(A a) {
this.a = a.a;
}
}
class B extends A implements I<B>{
private String b;
#Override
public void update(B b) {
super.update(b);
this.b = b.b;
}
}
class C implements I<C> {public void update(C c){}}
This code cannot be compiled, because super and sub-classes trying to implements the same interface but with different type arguments.
Interface I cannot be inherited with different type arguments (A,B), anyone has a workaround to solve this?
No workaround are possible with such a hierarchy : in B you want to implement the i interface with two distinct generic types : A and B.
Generics are designed to bring more type safety and this possible ambiguity defeats that. From the client of the class, why update(B b) would be valid but update(A a) would be not ?
So the compiler will never accept it.
But with composition you could do :
class B implements i<B>{
private A a;
private String b;
#Override
public void update(B b) {
super.update(b);
this.b = b.b;
}
}
And now you can use the A a field if needed from the B instance.
With the inheritance model given below, you'll achieve a contact of i through B in A. You don't really need to implement i for class B<T>.
See the example below:
interface i<T> {
}
class A<T> implements i<T> {
}
class B<T> extends A<T> {
}
Hope it helps you to understand the structure!
I do not understand what is needed, but this code is compiled))
interface i<T extends i<T>> {
void update(T t);
}
class A<Q extends A<Q>> implements i<Q> {
private String a;
#Override
public void update(A a) {
this.a = a.a;
}
}
class B<X extends B<X>> extends A<X> implements i<X> {
String b;
#Override
public void update(X b) {
super.update(b);
this.b = b.b;
}
}

Error with collections.sort (Bound mismatch)

I have to make an especific sort in a object. I read a lot of tutorials and utilized the class Comparable.
My Class:
public class PaAcao implements Serializable, IAcao, Comparable<PaAcao> /* Ordenar */ {
#Override
public int compareTo(PaAcao acaoCompara) {
//return this.aresta - outro.aresta;
int i = 0;
String[] array1 = this.cnrAcao.split(".");
String[] array2 = acaoCompara.cnrAcao.split(".");
for(String c : array1){
if (array2.length > i){
if (Integer.parseInt(c) > Integer.parseInt(array2[i]))
{
return 1;
}
if (Integer.parseInt(c) < Integer.parseInt(array2[i]))
{
return -1;
}
}
i++;
}
return -1;
}
For this Class i have an interface:
package br.com.agraria.qualidade.model.entity;
public interface IAcao{
public abstract String getCnmUsuarResp();
public abstract Usuario getusuarResp();
public abstract void setusuarResp(Usuario usuarResp);
public abstract PaStatusAcao getIcdStatus();
public abstract String getCnrAcao();
public abstract Boolean getLpublico();
}
And i get the error below:
public class PaAcaoServiceImpl extends HibernateGenericServiceImpl<PaAcao> implements PaAcaoService {
#Override
public List<? extends IAcao> processarAcoes(List<? extends IAcao> acoesProcessar) {
SessaoPrivilegiosGerente sessaoPrivilegiosGerente = sessaoService.getSessaoPrivilegiosGerente();
List<IAcao> macroRemover = new ArrayList<IAcao>();
Collections.sort(acoesProcessar);
...
}
}
The problem is in the line Collections.sort(acoesProcessar);
I get the message:
Bound mismatch: The generic method sort(List<T>) of type Collections
is not applicable for the arguments (List<capture#14-of ? extends IAcao>). The inferred type capture#14-of ? extends IAcao is not a
valid substitute for the bounded parameter <T extends Comparable<? super T>>
The resolution was (Thanks Deactivator2 for helping me with this):
Extends Comparable on the interface IAcao:
package br.com.agraria.qualidade.model.entity;
public interface IAcao extends Comparable<IAcao>{
public abstract String getCnmUsuarResp();
public abstract Usuario getusuarResp();
public abstract void setusuarResp(Usuario usuarResp);
public abstract PaStatusAcao getIcdStatus();
public abstract String getCnrAcao();
public abstract Boolean getLpublico();
}
And in my class PaAcao, I remove the implements of Comparable because it'll be duplicated and change the type os compareTo to IAcao and not PaAcao:
public class PaAcao implements Serializable, IAcao /* Ordenar */ {
#Override
public int compareTo(IAcao acaoCompara) {
//return this.aresta - outro.aresta;
int i = 0;
String[] array1 = this.cnrAcao.split(".");
String[] array2 = acaoCompara.cnrAcao.split(".");
for(String c : array1){
if (array2.length > i){
if (Integer.parseInt(c) > Integer.parseInt(array2[i]))
{
return 1;
}
if (Integer.parseInt(c) < Integer.parseInt(array2[i]))
{
return -1;
}
}
i++;
}
return -1;
}

Is this forbidden in Java Generics?

class Collator<S extends Stream<E extends Comparable<E>>> {
S s;
E e;
public <S> Collator(List<S> streams){
s = streams.get(0);
e = s.read();
}
public <E> E next(){
return e;
}
}
interface Stream<E extends Comparable<E>>{
public E read();
}
class Record implements Comparable<Record>{
public Integer time;
public int compareTo(Record r){
return this.time.compareTo(r.time);
}
}
Especially 1st line:
class Collator<S extends Stream<E extends Comparable<E>>>
I expect to say:
Define a collator that works on Streams of Entries where each Entry implements comparable.
you miss-qualified the generic parameters
class Collator<S extends Stream<E>,E extends Comparable<E>> {
S s;
E e;
public Collator(List<S> streams){
s = streams.get(0);
e = s.read();
}
public E next(){
return e;
}
}
interface Stream<E extends Comparable<E>>{
public E read();
}
class Record implements Comparable<Record>{
public Integer time;
public int compareTo(Record r){
return this.time.compareTo(r.time);
}
}
this compiles
in particular the line class Collator<S extends Stream<E>,E extends Comparable<E>> it means a Collator that works on a S that is a Stream of E and E implement Comparable
Some glass ball guessing, since you don't show your error message:
Your constructor and method are declaring new type parameters <E> and <S> which are shadowing the type parameters of your class. Remove them.
Then, E should be a type parameter of your class, too.
class Collator<E extends Comparable<E>, S extends Stream<E>> {
S s;
E e;
public Collator(List<S> streams){
s = streams.get(0);
e = s.read();
}
public E next(){
return e;
}
}
interface Stream<E extends Comparable<E>>{
public E read();
}
class Record implements Comparable<Record>{
public Integer time;
public int compareTo(Record r){
return this.time.compareTo(r.time);
}
}
The problem is E extends Comparable
Define a collator that works on Streams of Entries where each Entry implements comparable of a given type:
public class Collator<T,E extends Comparable<T>, S extends Stream<E>>

Categories