5

I am trying to generify following class:

public class FooService {

  private Client client;

  public Foo get(Long id) {
    return client.get(id, Foo.class);
  }

  public List<Foo> query() {
    return Arrays.asList(client.get(Foo[].class));
  }

}

Everything is alright except Foo[].class:

public abstract class BaseService<T, I> {

  private Client client;
  private Class<T> type;

  public BaseService(Class<T> type) {
    this.type = type;
  }

  public T get(I id) {
    return client.get(id, type);
  }

  public List<T> query() {
    return Arrays.asList(client.get(/* What to pass here? */));
  }

How can I solve this issue without passing Foo[].class in the constructor like I have done with Foo.class?

2 Answers 2

4

Java lacks facilities to obtain an array class from element class directly. A common work-around is to obtain the class from a zero-length array:

private Class<T> type;
private Class arrType;

public BaseService(Class<T> type) {
    this.type = type;
    arrType = Array.newInstance(type, 0).getClass();
}

You can now pass arrType to the client.get(...) method.

Sign up to request clarification or add additional context in comments.

5 Comments

I thought that too, but then idea warns me and says Unchecked cast: .... Is there a workaround for this as well?
@s.alem Does it warn you at the point of calling client.get or at the point of setting arrType in the constructor?
Sorry, that happens when I set Class<T[]>for arrType. When I define it as Class, it doesn't complain there. However it is say Unchecked assignment: ... in the method call client.get(arrType). I can live with that, but it would be cool if there's a workaround.
@s.alem If you make arrType a Class<T[]> then you need an explicit cast in front of the assignment, i.e. arrType = (Class<T[]>)Array.newInstance(type, 0).getClass(); otherwise it wouldn't compile. If this is where Idea complains of unchecked cast, there's little that could be done here, because getClass does not pass the actual type of the array. The method is on java.lang.Object, so it returns Class<?>.
I suspected that. Thank you very much.
1

Why don't you do something like this:

public class Client<T> {

  T instance;

  T get(long id) {
      return instance;
  }

  List<T> get(){
      return new ArrayList<>();
  }
}

class FooService<T> {

  private Client<T> client;

  public T get(Long id) {
      return client.get(id);
  }

  public List<T> query() {
      return client.get();
  }

}

1 Comment

It is probably not visible in this simplified example, but the client is actually out of my reach (3rd party). So this has to be handled in service layer. So in my case wrapping the client with another class only moves the same problem to another layer. But thank you anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.