26

This is the follow up of my question here: Weird Java generic.

If I have a code like this:

Casts.<X, T> cast(iterable[index]);

Can I add a static import and do:

<X, T> cast(iterable[index]);

Eclipse doesn't allow this. But after seeing so many bugs with static import in Eclipse, I'm not that certain.

Community
  • 1
  • 1
nanda
  • 24,458
  • 13
  • 71
  • 90

5 Answers5

13

No, you can't : I just confirmed this via some test code.

PS > javac -version
javac 1.6.0_04

Casts.java

public class Casts
{
    public static <From, To> To cast(final From object)
    {
        return (To)object;
    }
}

Test.java

import static Casts.cast;

public class Test
{
    public static void main(String[] args)
    {
        final Integer integer = new Integer(5);

        // This one compiles fine.
        final Number number = Casts.<Integer, Number>cast(integer);

        // This one fails compilation:
        // PS> javac Test.java
        // Test.java:11: illegal start of expression
        //             final Number number = <Integer, Number>cast(integer);
        //                                                    ^
        // Test.java:11: not a statement
        //             final Number number = <Integer, Number>cast(integer);
        //                                                        ^
        final String string = <Integer, String>cast(integer);
    }
}
bernard paulus
  • 1,644
  • 1
  • 21
  • 33
jdmichal
  • 10,984
  • 4
  • 43
  • 42
  • I tried something similar with the same results. But I can't find anything in the JLS that suggests that the second form *should* be invalid. – Dan Dyer Jan 12 '10 at 16:34
  • Thanks! Just one suggestion, it will be better if the method cast is implemented like this: public To cast(final From object) I discussed it here: http://satukubik.com/2010/01/06/java-tips-using-generic-correctly/ – nanda Jan 12 '10 at 16:34
  • Yea... I don't know WHY specifying the generic parameters causes this to happen. Just know experimentally that it does. I think static imports are the devil anyway, so I would never have known this otherwise. :) – jdmichal Jan 12 '10 at 16:36
  • @nanda Yes, that would be a better specification, as it prevents the possibility of a run-time `ClassCastException`, generating a compiler error instead. – jdmichal Jan 12 '10 at 16:38
  • @nando Note that `From` needs to extend `To` though. I tried specifying it as ``, but the compiler does not like that so much. It does accept `` though. – jdmichal Jan 12 '10 at 16:48
  • 1
    @Dan Dyer: you must search the JLS to find if it is valid: JLS-15.12 shows what is accepted – user85421 Jan 12 '10 at 19:01
  • @jdmichal: I think you're wrong... means there is no casting at all (from subtype to supertype, always correct), means casting (from supertype to subtype, may still wrong, which is the essence of casting). – nanda Jan 13 '10 at 09:20
  • @nanda Ah. I only accounted for up-casting, not down-casting. (It's still casting, even if there's no chance of error.) You would need to make both up-cast and down-cast methods to accommodate both situations using parameter wildcards. – jdmichal Jan 13 '10 at 19:01
9

No

If you want to provide an explicit type parameter when calling a generic static method, you must prefix the method with the class name, even if the method is statically imported.

Dónal
  • 185,044
  • 174
  • 569
  • 824
5

Java grammar allows type arguments only with typename specified. See corresponding section in JLS https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-MethodInvocation

Tibor Blenessy
  • 4,254
  • 29
  • 35
2

I'm pretty sure the answer is no--if you want to use a generic method call, you need an object to call it on (foo.<T>doSomething()). If the method is static, you need the class ( Foo.<T>doSomething() ).

This is even true if you're calling the method from elsewhere in the class itself. If you are working in a non-static method (i.e. in an instance method), you would call this.<T>doSomething().

Matthew Flynn
  • 2,210
  • 19
  • 27
  • almost everything in this answer is incorrect 1) You can definitely call static methods without using the class if the method is statically imported 2) You can call static methods on an object or a class, though the former is considered a bad practice 3) You do not need to prefix a static method with the class name within a class – Dónal Jan 12 '10 at 16:21
  • Yes, you can if you are not declaring the casting class within the generic brackets <>. If you do want to declare the cast, you need an object. Show me it working without. – Matthew Flynn Jan 12 '10 at 16:24
  • + 1 for mentioning this problem is not specifically related to static imports. – shmosel Dec 26 '14 at 03:30
2

As far as I've read, a shortcoming of the static import mechanism is that you must specify the calling object/class if you wish to provide formal parameters. In this example, it's not very clear why there are two generic parameters, but if you wish to avoid having to specify the calling object/class you can type hint through a cast of the arguments as such:

public static <E> E foo(E e) {}

Number n = foo((Number)3);

With the type hint, the type inference will return an object of type Number, instead of Integer as it would have reasoned otherwise.

  • Actually, public static E foo(Object obj) { return (E) obj; }; Number n = foo(3); works as well, tho you prolly need to suppress some warnings. – yihtserns Sep 04 '11 at 15:33