19

No static member can use a type parameter, but is it possible to call a static member using the generic type parameter? For example:-

abstract class Agent<A>{
    void callAgent();
    Agent(){
        A.add();                    
    }
}

Here add() is a static method.

There are some C# questions and answers on a similar topic but I'm not too sure how to go about it in Java.

aps
  • 2,452
  • 10
  • 35
  • 47

6 Answers6

10

No you cannot do it if A is a generic type. (Bozho answered to fast :) and probably thought A was concrete type.

What will work is the following.

abstract class Agent extends Blah<ConcreteA>{
    void callAgent();
    Agent() {
        ConcreteA.add();
    }
}

but it's probably not what you want to do.

After reading your comments it sounds like what you really want to do is:

abstract class Agent<A extends SomeClassThatSupportsAdd> {

    void callAgent();
    protected abstract A createNew();

    Agent() {
        A a = createNew();
        A.add();
    }
}

Your subclasses will have to override createNew().

If you still do not like that you can take a look at AspectJ which will allow you to do some constructor magic (see how spring does @Configurable) but that gets far trickier and complicates things.

Another option is Scala. Java does not do inheritance on static methods so you can't get parameterized modules (groups of functions in some languages this is called a functor ... ocaml). However Scala supports a singleton "object" that does allow for parametric functional polymorphic inheritance.

fishjd
  • 1,617
  • 1
  • 18
  • 31
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • this is exactly what I want to do. I don't need the add method anymore because in the add method I would have created a new instance of the generic type.that is now being done by the createNew() method.thanks a lot. i would override the createNew() in different types of Agents and return the instance to the base class Agent.any loopholes? – aps Jun 28 '11 at 20:52
  • 2
    Why do you need to create a new instance from A to call a static method ? – M.Sameer Sep 23 '11 at 19:21
  • Because A is not really a Class and in this case the method "add" is not a static method. 'A' is a "Type" or in other terms a placeholder. In Java "Types" cannot have static methods, instance methods, or even constructors. Instances of Types can have methods but instances (ie new Object()) do not have static methods. In Java only Classes can have static methods. – Adam Gent Sep 24 '11 at 00:37
9

No, you cannot. The compiler does not know A (which resolves to Object) has the add method.

And you shouldn't need to invoke static methods on generic types in the first place. If you want specific behaviour for each type, define it as non-static, use extends BaseClass in the generics declaration, and invoke it.

Technically, you can also invoke a static method that way, but it's ugly:

class Base {
    public static void add() { }
}

class Foo<A extends Base> {
    void bar() {
        A a = null; // you can't use new A()!
        a.add();
    }
}
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • @Bozho hey what is getInstanceOfA(); ? So you can actually create new instances of generic type parameters from a generic class? Please explain. – aps Jun 28 '11 at 20:05
  • No, you can't. That's why I assumed you have one. Check my update though – Bozho Jun 28 '11 at 20:07
  • @Bozho thanks...actually I plan to create the instance of the generic type in the add method itself, since new can't be used in the generic class. That's why I wanted it to be static. Do you have a better way? – aps Jun 28 '11 at 20:16
  • @aps you can construct the object dynamically by using reflection to call the generic classes constructor. I will say Scala solves your problem much more elegantly with its companion objects. – Adam Gent Jun 28 '11 at 20:31
  • @Adam "you can construct the object dynamically by using reflection to call the generic classes constructor" could you please explain this a bit?thanks... – aps Jun 28 '11 at 20:42
  • @aps I don't recommend doing that ... see edits to my answer. – Adam Gent Jun 28 '11 at 20:45
2

This is not possible because the A type will not necessarily contain an add() method. The compiler will not permit this, because it can't guarantee that it will work.

Marcelo
  • 11,218
  • 1
  • 37
  • 51
1

In fact, you can invoke a static method on a type parameter (although it isn't done dynamically).

Try this:

public class Main<T extends Collections> {

    public static void main(String[] args) {
        new Main<>().foo();
    }

    void foo() {
        List<Integer> list = Arrays.asList(2, 3, 1);
        T.sort(list);
        System.out.println(list);
    }
}

I have no idea why the language designers decided it was a good idea to allow this.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
1

It is handy to get a value from an enum you don't know beforehand.

public static <T extends Enum<T>> T enumFromName(String name, Class<T> clazz) {
    return StringUtils.isEmpty(value) ? null : T.valueOf(clazz, name);
}

Having:

enum ProductType { FOOD, ELECTRONICS, ... }

You can do:

ProductType p = enumFromName("FOOD", ProductType.class);

I guess you can also take advantage of this in your own classes, although I would not recommend using static too much.

Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100
1

You can use reflection for calling static method of class T. For example:

public Agent<T>{

    private final Class<T> clazz;

    public Agent(Class<T> clazz){
        this.clazz = clazz;
        executeAddMethodOfGenericClass();
    }

    public void executeAddMethodOfGenericClass() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = clazz.getMethod("add");
        method.invoke(null);
    }
}

But i can get exception. Be careful.

Alex
  • 658
  • 6
  • 8