How to bind the type variable of a method that can

2019-09-04 01:15发布

问题:

I have two classes called Matchers with static methods that I need to use in a third class, so one of them can only be used via static imports. However, I cannot explicitly specify type parameters (i.e. <Type> method()) for statically imported methods.

How can I work around this without having to fully qualify the class?

回答1:

You cannot. At least not in Java (some other languages, for instance Scala, let you give an alias to a class you import which is kind of cool and can be used exactly in such a case).

Here you just need to either use the fully qualified name for both classes or for one class (and import the other one).

Using 2 classes with the same name in one file isn't the best idea unless you have a really good use case for it. Maybe you can actually do what you want using only one of the Matchers?

I'm going to do some mind reading here but I'd guess this is something along the lines of Hamcrest/Mockito Matchers? If so then in most cases you should be ok with using only one of them. If you're in the very unfortunate case where you do need both then, well, you're unfortunate :-)



回答2:

Came up with a very hacky way just as an alternative to fully qualifying the class:

Simply implement a sub-class of class in question and call the parent class static method on the sub-class. This is allowed and does not even generate compiler warnings. Since the method is static, no virtual method stuff is involved. The sub-class simply serves as an alias (so better make it private and final and stuff).



回答3:

There is a way that might look a bit unclean but it’s covered by the standard. You can abuse local variables as imports. Since their value doesn’t matter for static method invocations they can be initialized to null

public class Imports
{
  static <T> java.util.List<T> emptyList()
  {
    System.out.println("Imports.emptyList()");
    return java.util.Collections.emptyList();
  }
  public static void main(String[] args)
  {
    final java.util.Collections c=null;
    final Imports i=null;
    System.out.println(c.emptyList());
    System.out.println(i.emptyList());
  }
}

c.emptyList() and i.emptyList() refer to different static methods here. And you may even insert type arguments, e.g. c.<String>emptyList(). But some compilers might issue warnings you have to switch off for a class using this trick. But in some cases there might be no better way (repeating qualified names lots of times is not always a better way)…