views:

120

answers:

7

I'm trying to make a method that takes an argument of Country.class, User.class etc, and returns argument.count().

All the possible classes that I would give to this method extend from Model and have the method count().

My code:

private static long <T> countModel(Model<T> clazz)
{
    // there is other important stuff here, which prevents me from
    // simply by-passing the method altogether.

    return clazz.count();
}

Called by:

renderArgs.put("countryCount", countModel(Country.class));

However this just doesn't work at all.

How do I do this, please?

+2  A: 

Don't fully understand what you are trying to achieve. Did you mean this?

private static long <T> countModel(Model<T> model)
{
    return model.count();
}

renderArgs.put("countryCount", countModel(country));

EDIT: If count is a static method, it has nothing to do with model. The static method is not inherited. So all you have to do is to call it directly,

renderArgs.put("countryCount", Country.count());
ZZ Coder
No, the classes have `count()` as a static method, not the objects. Sorry if I'm not clear.
Coronatus
See my edit ....
ZZ Coder
The first part doesn't even compile so I don't think that this is what the OP meant :)
Pascal Thivent
A: 

In the line

renderArgs.put("countryCount", countModel(Country.class));

you call countModel with a Class<Country>, but you have to call it with an instance of Country like this:

Country country = new Country();
renderArgs.put("countryCount", countModel( country );
tangens
A: 

You are passing Country.class which is a Class object. How is it a Model object?

fastcodejava
A: 

You are not passing an instance of country here, you are passing a Class object:

renderArgs.put("countryCount", countModel(Country.class));

You need to instantiate A model and pass it as an argument:


Model model = new Country();
renderArgs.put("countryCount", countModel(model));

or


Country country = new Country();
renderArgs.put("countryCount", countModel(country));

In this case, Country.class is an object of the Class<Country> type.

marcos
A: 

In reply to your comment to ZZ Coder; a static method in Java is called in the namespace context of a class, like Model.count() for a static method count() in the class Model, but the method does not become part of Model.class, Model.class is an instance of Class describing the class Model. (I can see where the confusion originates, it would be logical to have a specialised Model.class that includes the static methods, but Java isn't desinged that way.)

Your way out is to use reflection to call the static count() for the class that you pass to your code.

rsp
+4  A: 

I think you want to do

private long countModel(Class<? extends Model> clazz) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
  Method countMethod =  clazz.getDeclaredMethod("count", null);
  return (Long) countMethod.invoke(null, null);
}

Hopefully something like this would work (my reflection skills are not really that good).

Andrei Fierbinteanu
This is it! Just needed to take out the "null" arguments and it worked. Thank you.
Coronatus
+1  A: 

Clarifying, you want a class (A) that is constrained to have a particular class method (B) and you want to pass that class as an argument to some other method (C) and have that method (C) invoke that class method on that class (A.B())?

The first part, the type constraint, that can't be done. Java's type system just does not work that way.

The second part, passing a class as an argument and invoking a class method on it, that can be done using reflection. This is how to do it, correcting from your code (though you should be more careful with the exceptions than I've been in this).

private static <T extends Model> long countModel(Class<T> clazz) throws Exception
{
    return (Long) clazz.getMethod("count").invoke(null);
}

The null is the instance to invoke this on (no instance; it's a class method). The cast to Long is required as the result of invoke() is an Object. The type parameter must go before the result type. And the whole thing can take any class that is a subclass of Model as a parameter; it will just fail at runtime if the count method isn't present. Them's the breaks.

(Also note that if you wanted to pass arguments to count(), you'd have to specify the classes of those arguments to getMethod and the values themselves to invoke, in both cases as subsequent arguments. Both support Java5 variable argument lists.)

Donal Fellows
Thanks, this works. frosty_hotboy was first so I gave him the tick.
Coronatus