简体   繁体   中英

How to prevent type erasure?

I have a method that i want to refactor, and it looks (well, very much simplified) like this:

import com.sun.tools.javac.util.Pair;

private int foo(Pair<String, ?>... params) {
    if (params[0].snd instanceof String) {
        // do something
        return 0;
    } else if (params[0].snd instanceof ArrayList) {
        // do something else
        return 1;
    }
    return -1; // realistically in the code base, this line will never happen **edit: disregard this line
}

so i was thinking i'd do something like split it up into two methods so that i don't have to do type checking. (is this even a good refactor?)

so i wanted to do something like this:

private int foo(Pair<String, String>... params) {
    // do something
    return 0;
}

private int foo(Pair<String, ArrayList>... params) {
    // do something else
    return 1;
}

But the compiler keeps telling me that both foo() methods have the same type erasure. Is java just erasing everything that Pair<A, B> knows? If so, what's the best way to refactor then? (or does it need refactoring)

At compile time Java will erase the type information of Generics. There is no way to prevent that. At runtime, Pair doesn't have <A,B> it is effectively <Object,Object> .

As for refactoring it, there are a few things you might prefer (but apart from one recommendation) there's not much that could be improved in your example - I'd probably use a single else (if that last line can't happen. And I'd use a List instead of a specific type of List.

private int foo(Pair<String, ?>... params) {
  if (params[0].snd instanceof String) {
    return 0;
  } else { //if(params[0].snd instanceof List) { //is a List interface, not which List
    // do something else
    return 1;
  }
// return -1; // If it can't happen, why have it here.
}

I would add that

private int foo(Pair<String, String>... params) {
    return 0;
}

private int foo(Pair<String, ArrayList>... params) {
    return 1;
}

if this code were allowed, it wouldn't have much use. You know what type you're passing into foo. It's whatever the type of the reference is, not the type of the actual object. So just replace all calls to this where you'd pass a Pair<String, String> with just 0 .

That is, which method is called should be determinable at compile time. Not at runtime. And if it's determinable at compile time, you don't need to call the method at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM