2

I have a method in my Android app that can either display from a List of Drawables or Strings (representing the image URLs).

I tried to make two constructors but got the type erasure error. Now I am using a generic argument and check a member for being a String to represent the URL, like so. In the alternate case I assume that it will be a List of Drawables. Something like this:

setImages(List<?> images) {
    this.images = images;
    if (String.class.isInstance(images.get(0) ) ) {
        isImageUrl = true;
    }
}

Is there a way to do this better, somehow preserve type safety ?

Saad Farooq
  • 13,172
  • 10
  • 68
  • 94

3 Answers3

3

Why not just use 2 separate methods?

void setImages(List<Drawable> images) {
 // do something
}

void setImagesFromStrings(List<String> images) {
 // do something else
}
James Goodwin
  • 7,360
  • 5
  • 29
  • 41
  • You could always have different method names if they are setting the images in different ways, e.g. `setImages(List images)` and `setImagesFromStrings(List images)` – James Goodwin Feb 20 '12 at 14:18
  • That's actually a pretty good idea. Now why didn't I think of that... I'm actually using this in a constructor as well so I'm going to overload that by using a dummy parameter. Type safety preserved problem solved. – Saad Farooq Feb 20 '12 at 14:28
  • 1
    And to think you're answer started as the most unreasonable... lucky you didn't get a downvote... and look at you now.... good work – Saad Farooq Feb 20 '12 at 14:29
1

No, there is no real way to do that.

There has been some interesting solution here, but I don't think it applyes for you.

Personnally, I prefer to pass the class as a parameter for the method like

setImages(List<? extends T> images, Class<T> clazz) {
    this.images = images;
    if ( clazz == String.class  ) ) {
        isImageUrl = true;
    }
}
Community
  • 1
  • 1
Snicolas
  • 37,840
  • 15
  • 114
  • 173
1

A better object oriented way to solve you problem would be to have an intermediate interface that provides the method you are looking for, but this will force you to wrap String into something else

interface Displayable {
  public boolean isRealImage();
}

class StringImage implements Displayable {
  public String name;
  public boolean isRealImage() { return false; }
}

class DrawableImage implements Displayable {
  public Drawable drawable;
  public boolean isRealImage() { return true; }
}

setImages(List<? implements Displayable> images) {
    this.images = images;
    if (images.get(0).isRealImage()) {
      isImageUrl = true;
    }
}

Of course this solution, while quite overkill, is meant to allow you whatever you need to do with your classes.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • It does seems a bit of overkill and I probably won't use it but at least type safety is preserved so +1 – Saad Farooq Feb 20 '12 at 14:17
  • 1
    Yes, you asked for a type safe solution not for a slick one.. in a verbose language like Java they are often at antipodes ;) – Jack Feb 20 '12 at 14:21