1

These two examples don't compile using Oracle Java 8 JDK.

The error is:

error: incompatible types: Object cannot be converted to Integer for (Integer i : foo.set )

Example 1)

import java.util.Set;

class Foo<T>
{
    protected Set<Integer> set;
}

class Foo2 extends Foo
{
    void doit()
    {
        for (Integer i : set )
        {

        }
    }
}

Example 2)

import java.util.Set;

class Foo<T>
{
    public Set<Integer> set;
    public static void main( String[] args )
    {
        Foo foo = new Foo();
        for (Integer i : foo.set )
        {

        }
    }
}

Is it bug or feature? As I can understand generics don't work in fields оf raw type.

Evan Knowles
  • 7,426
  • 2
  • 37
  • 71
Denis Pimenov
  • 19
  • 1
  • 1
  • 1
    Strangely, this does compile if you construct `Foo` as a typed object, even if it's not typed as `Integer` - say, `Foo foo = new Foo<>();` – Evan Knowles Mar 23 '17 at 10:13
  • 1
    It is possibly because you use a raw type, all type information is erased on all its containing fields, e.g. `Set` becomes `Set`. – MC Emperor Mar 23 '17 at 10:16
  • Why do you use raw types anyway? – MC Emperor Mar 23 '17 at 10:42
  • @MCEmperor it was bug in real code (after refactoring generics were added in ancestor class, but forget about descendants ) and I was need some time to found reason - it was not obvious. – Denis Pimenov Mar 23 '17 at 10:51

1 Answers1

0

Its not an error. You need to pass a generic type to create new instance:

class Foo<T>
{
  public Set<Integer> set;
  public static void main( String[] args ) {

      Foo<Integer> foo = new Foo();  // changed code

      for (Integer i : foo.set )
      {

      }
    }
}
Krishnanunni P V
  • 689
  • 5
  • 18
  • 32
  • The point was that the type parameter `T` isn't actually being used. The error wasn't on creating a new instance, the code in the question just creates a raw type. – Evan Knowles Mar 23 '17 at 10:22
  • I understand this, I made raw type consciously. Raw types is not forbidden in java. And here Set it's not raw type, it's inside raw Foo. Compiler ignore all field types in raw object Foo. It's strange. – Denis Pimenov Mar 23 '17 at 10:32
  • @DenisPimenov **Don't. Ever. Use. Raw types.** The only reason they're not forbidden is because of backward compatibility. But when writing new code, **always** use type parameters. See [this post](http://stackoverflow.com/a/2770692/507738). Plus, even the [JLS, §4.8](https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.8) states that it might *"disallow the use of raw types"*. – MC Emperor Mar 23 '17 at 10:38
  • @DenisPimenov What is strange about it? It is documented, that when using a raw version of a generic class, then ___every___ generic type in that class will be erased. So you don't have `Set`, you have `Set`. – Tom Mar 23 '17 at 10:42