-1

I have a need to pass a value of Map<String, String> type to Android's AsyncTask. Unfortunately AsyncTask's callback doInBackground(Params... params) and execute(Params... params) method accept varargs. We know that varargs gets turned into arrays and we cannot create arrays of generic types. How can I pass my parameter to execute?

Sandah Aung
  • 5,712
  • 15
  • 48
  • 94

1 Answers1

1

Generics are just mostly there to warn you about doing bad stuff at compile time. To get the varargs with generics going, you can use a wrapper as shown below:

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class VarArgsGeneric {

public static void main(String... args) {

    StringMapWrapper mw1 = createMap("1", "one");
    StringMapWrapper mw2 = createMap("2", "two");
    StringMapWrapper mw3 = createMap("3", "three");

    VarArg<StringMapWrapper> test = new VarArg<StringMapWrapper>();
    test.add(mw1, mw2, mw3);
    test.add((StringMapWrapper)null);
    StringMapWrapper[] mws = test.getParams(StringMapWrapper.class);

    System.out.println(Arrays.toString(mws));
}

public static StringMapWrapper createMap(String key, String value) {

    StringMapWrapper mwrapped = new StringMapWrapper(new HashMap<String, String>());
    mwrapped.getMap().put(key, value);
    return mwrapped;
}

static class VarArg<Param> {

    private final List<Param> allParams = new ArrayList<Param>();

    // Heap pollution: http://stackoverflow.com/q/12462079/3080094
    @SafeVarargs
    public final void add(Param... params) {

        for (Param p : params) {
            allParams.add(p);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T[] getParams(Class<T> type) {

        // Copied from http://stackoverflow.com/a/530289/3080094
        final T[] pa = (T[]) Array.newInstance(type, allParams.size());
        for (int i = 0; i < pa.length; i ++) {
            pa[i] = type.cast(allParams.get(i));
        }
        return pa;
    }
}

static class StringMapWrapper {

    private final Map<String, String> m;

    public StringMapWrapper(Map<String, String> m) {
        this.m = m;
    }

    public Map<String, String> getMap() {
        return m;
    }

    @Override
    public String toString() {
        return m.toString();
    }
}
}

Which prints:
[{1=one}, {2=two}, {3=three}, null]

vanOekel
  • 5,542
  • 1
  • 17
  • 46