Java generic type's inferring - java

I have class structure like this:
class A1,A2,..,An extends A;
class B1,B2,..,Bn extends B;
And class that converts Ai into Bi:
private B1 convert(A1 a1){}
...
private Bn convert(An an){}
How can I define single public method with signature like <? extends B> convert(<? extends A> a)?
Now I have only this approach:
B convert(A a){
if(A.getClass().equals(A1.class)){
return convert((A1)a);
}...
}
Can I use instanceof if perfomance is important and the method will be called frequently?

A more elegant solution will probably be to declare a method in A: [preferably abstract, if A is abstract]:
public abstract B toB();
Overriding classes (A1,A2,...) will have to override it and instantiate their own B object.
Code snap [the static modifier is used since I implemented it as an inner class, it is not needed and cannot be used if the classes are outer classes]:
public abstract static class A {
public abstract B toB();
}
public static class A1 extends A {
#Override
public B1 toB() {
return new B1();
}
}
public static class B {
}
public static class B1 extends B {
}

you could do something like:
public <AType extends A, BType extends B> BType convert(AType a) {...
But your could have converter interface like:
public interface Converter<AType extends A, BType extends B> {
AType convert(BType b);
BType convert(AType a);
}
Regarding the performance question, you could take a look here

Related

Call generic method with interface constraints on objects who may implement that interface

This is my code:
interface a {}
class b{}
class c extends b implements a{}
class d extends b{}
class e{
public void makeItWork(){
b[] bees = new b[] {new c(), new d()};
for (b bee: bees){
if (bee instanceof a) {
a beeA = (a) bee;
//how to call the method test if object bee conforms the the interface?
test(beeA.getClass(), beeA);
//this goes wrong
}
}
}
public <T extends a> void test(Class<T> classType, T concrete){
}
}
Besides maybe the bad design, I would like to know if it is possible to call the method test on objects who implements the interface a.
your test method doesn't need a generic type parameter.
You can define it as:
public void test(Class<? extends a> classType, a concrete) {
}
P.S. please use capitalized class names.
You can actually get away without using generics at all here:
public void test(a concrete) {
}

Generic Constructor call in inheritance

I have the following scenario :
public abstract class A{}
public class B extends A{}
public abstract class C<T extends A>{
private T t;
public C(){}
public C(T t){
this.t = t;
}
}
public class D<B> extends C<A>{
private B b;
public D(B b){
super(b);
this.b=b;
}
}
But i am getting an error in the constructor of class D. What am i missing? Java 1.7
In the code you gave, B (the generic parameter of D) doesn't have to extend A so the bound of generic parameter from C is not satisfied.
Change D<B> extends C to D extends C<B>.

seek for help on java generic method

I have following class structure,
abstract class AbstractA {...}
class A1 extends AbstractA {...}
class A2 extends AbstractA {...}
abstract class AbstractB<T extends AbstractA> {
public void handle(T a) { ... }
}
class B1 extends AbstractB<A1> {
public void handle(A1 a) {
super.handle(a);
...
}
}
class B2 extends AbstractB<A2> {
public void handle(A2 a) {
super.handle(a);
...
}
}
Now I want to implement a generic method that would take a list of AbstractB and related AbstractA as parameters. e.g.
Handler.<B1, A1>handle(listOfB1, A1);
Handler.<B2, A2>handle(listOfB2, A2);
and
Handler.<B1, A2>handle(listOfB1, A2);
Handler.<B2, A1>handle(listOfB2, A1);
is not allowed.
I tried
class Handler {
// public static <T extends AbstractB<K extends AbstractA>, K extends AbstractA> handle(List<T> list, K a) {
public static <T extends AbstractB<? extends AbstractA>, K extends AbstractA> handle(List<T> list, K a) {
for (T tmp : list) {
tmp.handle(a);
}
}
}
but both does not compile. Can anyone help and give me any clue? Thanks!
Change it to :
public static <T extends AbstractB<K>, K extends AbstractA> void handle(List<T> list, K a) {
for (T tmp : list) {
tmp.handle(a);
}
}
Note that your method was missing a return type (I'm assuming your intended a void return type).
However, the main issue was that the type bound of T should be extends AbstractB<K> and not extends AbstractB<? extends AbstractA>.
Consider what happens in your current definition of the static handle method.
The current signature of the static method allows this call :
List<B1> listOfB1;
Handler.<B1, A2>handle(listOfB1, A2);
But in the body of the static method, you can't pass an A2 instance to the handle method of a B1 instance, which is why your code doesn't pass compilation. Therefore the type bound of T must depend on K.

Guice, extending interfaces and constructor return type

Interface A and its implementation:
public interface A<K, E> {
public void foo();
}
public abstract class AImpl<K, E> implements A<K, E> {
public void foo(){};
}
Interface B, which extends interface A, and its implementation:
public interface B extends A<Integer, String> {
public void bar();
}
public class BImpl extends AImpl<Integer, String> implements B {
public void bar(){};
}
An abstract class C, which gets A injected:
public abstract class C<K, E> {
A<K, E> a;
#Inject
public setA(A<K, E> a){
this.a = a;
}
public A<K, E> getA(){
return a;
}
}
With Guice:
bind(new TypeLiteral<A<Integer, Book>>(){}).to(BImpl.class);
And the last class, which extends class C:
public class D extends C<Integer, String> {
public void fooBar(){
this.getA().bar(); //Gets BImpl injected by Guice, and call bar(): Not working - error
((B) this.getA()).bar(); //Working
}
}
Like you can see from inline comments, BImpl gets properly injected and can be used, if it has no additional methods, that extends A (interface B is empty). If I add any new method in B, I can't call it in D without it casting to B. My main goal is, giving a user possibility to extend A and use this functionality in D.
If I add any new method in B, I can't call it in D without it casting to B. My main goal is, giving a user possibility to extend A and use this functionality in D.
If the user needs the functionality provided by B but not A, they should declare that they need a B. Class D should declare what it needs - not rely on casting to make sure it was correctly configured beyond what was declared.

Bind two generic types

I have a question regarding generics.
I have the following interfaces:
public interface InterfaceA<B extends InterfaceA.InterfaceB> {
public interface InterfaceB<A extends InterfaceA> {
void setA(A a);
}
}
And the following abstract implementation of InterfaceA:
public abstract class AImplOne<B extends InterfaceA.InterfaceB> implements InterfaceA<B> {
private final B b;
public AImplOne(B b) {
this.b = b;
b.setA(this); // <-- Unchecked call...
}
}
Its clear to me, that the call b.setA(this) is unchecked - but I don't like it, so I tried a second abstract implementation:
public abstract class AImplTwo<A extends InterfaceA, B extends InterfaceA.InterfaceB<A>> implements InterfaceA<B> {
private final B b;
public AImplTwo(B b) {
this.b = b;
b.setA((A)this); // <-- Unchecked cast
}
}
And again, its clear to me, that the call b.setA((A)this) is an uncheck cast.
But how should this be implemented or redesigned in order to get rid of the unchecked code?
You are actually having a mutual recursive generic definition that you break by using raw types: in
b.setA((A)this); // <- Unchecked cast
this is of type InterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA>>, but it should be of type InterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA<? extends InterfaceA.InterfaceB<...>>>>. You would have to use instead
public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {
public interface InterfaceB<A extends InterfaceA<B>> { //<- cannot make a static reference to the non-static type B
void setA(A a);
}
}
but you cannot use B, which is non-static, in the static interface declaration (interface declarations are always static).
For detail, one further try: Using the alternative
public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {
public interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>> {
void setA(A a);
}
}
abstract class AImplTwo<B extends InterfaceA.InterfaceB<A>, A extends InterfaceA<B>> implements InterfaceA<B> {
private final B b;
public AImplTwo(B b) {
this.b = b;
b.setA((A)this); // <-- Unchecked cast
}
}
causes again an unchecked cast, since now the nested type parameter of InterfaceA in interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>> is again an arbitrary subclass of InterfaceA.InterfaceB<?>.
Update, since you've asked for a general design:
I would think of InterfaceB (in fact, interfaces in general) as abstraction from a concrete implementation: You only need the interface InterfaceB, not its implementation details, in your implementation of InterfaceA. Think of InterfaceB as a contract, and you do not care about the implementation. Hence there is no need for binding the implementation of InterfaceA to the implementation of InterfaceB:
public interface InterfaceA {
public interface InterfaceB {
void setA(InterfaceA a);
}
}
Only if, for reasons I can't see, you do want to have the same type for all instances of InterfaceB that you are using, you need generics. Vice versa for InterfaceA. With the last generics example above, you can at least fix the types for InterfaceA and InterfaceB, and would only have to dynamically assert that A's B and B's A are the same.
Showing that no type checked solution exists in Java is difficult, but maybe it becomes plausible with the following example, which would be a solution if Java allowed the combination of extends and super:
public interface A<TB extends A.B<?>> {
public interface B<TA extends A<? extends A.B<?>>> {
void setA(TA a);
}
}
class AImplTwo<TB extends A.B<TA>, TA extends AImplTwo<TB, TA> super AImplTwo<TB, TA>> implements A<TB> {
private final TB b;
public AImplTwo(TB b) {
this.b = b;
b.setA((TA)this);
}
}
...come to think of it, the Pluggable Type System, which adds further typing to Java, allows this combination of extends and super, and might therefore offer a solution to your problem. But I find it too complex for what you get, and would either stick with simply using Interfaces without generics or some unchecked cast.

Categories