2

I'm using Oracle JDK 7u79. I don't know why the code below produces compilation error:

package generics;

import java.util.Collection;
import java.util.Collections;

class SomeClass {
    public Collection<String> getStringCollection() {
        return Collections.singleton("hello");
    }
}

class SomeTypedClass<T> {
    public Collection<String> getStringCollection() {
        return Collections.singleton("hello");
    }
}

public class SomeTest {
    public static void main(String[] args) {
        final int length1 = new SomeClass()     .getStringCollection().iterator().next().length();
        final int length2 = new SomeTypedClass().getStringCollection().iterator().next().length(); // compilation error
    }
}

Error:

Error:(21, 89) java: cannot find symbol
  symbol:   method length()
  location: class java.lang.Object

I've specified constant generics type Collection<String> as method parameter for getStringCollection() so I think both SomeClass and SomeTypedClass should be compiled without error.

Why this happen? And what is the proper solution which is getting constantly typed Collection without casting?

Kohei Nozaki
  • 1,154
  • 1
  • 13
  • 36

1 Answers1

2

Actually, since your SomeTypedClass<T> expects a type T passed in, even though it's not using the type, you'll need to do this in SomeTest:

public class SomeTest {
    public static void main(String[] args) {
        final int length1 = new SomeClass()     .getStringCollection().iterator().next().length();
        final int length2 = new SomeTypedClass<String>().getStringCollection().iterator().next().length(); // no more compilation error
    }
}

I used a String, but you could use Object if you wanted to since T isn't actually being used.

It may be worth considering doing something more like this with your SomeTypedClass class, depending on what your real-world scenario is:

class SomeTypedClass<T> {
    public Collection<T> getTypedCollection(T object) {
        return Collections.singleton(object);
    }
}

You could then do:

final int length2 = new SomeTypedClass<String>().getTypedCollection("hello").iterator().next().length();

If you're only interested in classes that derive from String, you could also do something like this:

class SomeTypedClass<T extends String> {
    public Collection<T> getStringCollection(T object) {
        return Collections.singleton(object);
    }
}

You could then do:

final int length2 = new SomeTypedClass<String>().getStringCollection("hello").iterator().next().length();
Ken Slade
  • 343
  • 2
  • 8
  • Nice, But it looks bit awkward because `` has completely no meaning. I don't want to put it everywhere... – Kohei Nozaki Dec 01 '15 at 06:09
  • Thanks for the edit, It makes sense if I want to use `` as something like `Collection getTypedCollection()` but unfortunately I don't want any variable type for that method. Instead, I want a constant generics type for that method in my real-world scenario. I'll use `` for other methods but not for that particular one. – Kohei Nozaki Dec 01 '15 at 06:17