0

I am trying to create a function that takes in a generic Class, does some work with a function of that Class, then return an instance of said Class.

I'm getting a compiler error: error: cannot select from a type variable - [ERROR] T.getManagers(), T.class);. Here is the function:

public static <T extends Bar> T getFoo(Class<T> fooClass , String person)
{
    T foo = null;
    try
    {
        Configuration config = Configuration.getConfiguration(person);
        foo = (T) Bar.getInstance(config,T.getManagers(), T.class);
    }
    catch (Exception e)
    {
        logger.error("Error", e);
    }
    return foo;
}

EDIT: Is there a way I can get around calling Bar.getManagers()? What I'm trying to do with generics is that I have say 5 classes very similar to Bar but not exactly the same. They all have getManagers(). By using a generic like T.getManagers() I'm trying to get around calling the explicit names in the code and using a generic one instead.

gjw80
  • 1,058
  • 4
  • 18
  • 36
  • `getManagers()` is method of `Bar` class? – Simon Dorociak Apr 17 '14 at 13:57
  • 1
    You cannot call a static on a generic. There is no way to ensure that every implementation of Bar implements a static getManagers() method. – jgitter Apr 17 '14 at 13:57
  • Yes, it's a public static method. – gjw80 Apr 17 '14 at 13:57
  • 1
    The `T.getManagers()` should probably be `Bar.getManager()`. And `T.class` should probably be `fooClass`. But you might have to post your `Bar` class and the `getInstance` method for more focussed help. – Marco13 Apr 17 '14 at 13:59
  • Please post the code of `Bar`, and in particular `getInstance()`. I definitely agree with @Marco13, we can't really help you with what you currently provided. – Joffrey Apr 17 '14 at 14:19

3 Answers3

2

You're trying to use constructs that are not allowed in Java:

  • You can't use T.getManagers(), because it is a static method, and the class T won't be available at runtime (type erasure). If the getManagers() method exists in class Bar (and it should*), then use Bar.getManagers() instead.

  • You can't use T.class for the same reason, the class T won't be available at runtime. Use fooClass instead.

The code you provided should look like:

public static <T extends Bar> T getFoo(Class<T> fooClass , String person) {
    T foo = null;
    try {
        Configuration config = Configuration.getConfiguration(person);
        foo = (T) Bar.getInstance(config, Bar.getManagers(), fooClass);
    } catch (Exception e) {
        logger.error("Error", e);
    }
    return foo;
}

(*) This method should be in Bar because it seems to be a common behaviour that you use here, and that you seem to expect from all Ts that could extend Bar. There is no such thing as inheritance for static methods.

Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • I tried to use fooClass in place of T and got this error: `error: cannot find symbol [ERROR] fooClass.getManagers(), fooClass.class);`. – gjw80 Apr 17 '14 at 14:06
  • Try `fooClass`, not `fooClass.class` – Joffrey Apr 17 '14 at 14:07
  • `fooClass.getManagers()` is forbidden. You should use `Bar` instead, as I stated in my answer. – Joffrey Apr 17 '14 at 14:09
  • I can't use Bar, the point of the method is there are 4 other classes I need to call and I'm trying to do it with a generic. So if I always call `Bar` then when I need to get a manager for `XYZ` I'm still calling `Bar`'s getManagers(), not XYZ's. – gjw80 Apr 17 '14 at 14:13
  • You can't use static methods this way. Use instance methods instead, then you'll be able to use inheritance. I think you're misusing generics here, I don't understand what you're trying to do. It's hard to give design advice without more info on your use case. Please provide your actual code. – Joffrey Apr 17 '14 at 14:15
1

T.class is prohibited construction, you cannot use it because of type erasure. Please take a look on a workaround

Community
  • 1
  • 1
nikis
  • 11,166
  • 2
  • 35
  • 45
0

You can use reflection on the fooClass object to obtain and execute the getManagers() method. It will fail at runtime if the class doesn't have the method though.

public static <T extends Bar> T getFoo(Class<T> fooClass , String person)
{
    T foo = null;
    try
    {
        Configuration config = Configuration.getConfiguration(person);
        Method getManagers = fooClass.getDeclaredMethod("getManagers");
        foo = (T) Bar.getInstance(config, getManagers.invoke(null), T.class);
    }
    catch (Exception e)
    {
        logger.error("Error", e);
    }
    return foo;
}

This is not a great practice, but should work.

matts
  • 6,738
  • 1
  • 33
  • 50