Bardya Momeni
Bardya Momeni

Reputation: 337

Define instance generic type later on in code in Java

I have a class like this:

public class Foo<T>
{
//What ever inside
}

And later on I want to do something like this:

public class MyClass
{
    Foo foo;
    public MyClass(int x)
    {
       if(x==1)
       {
           foo = new Foo<Integer>();
           //EDIT1
           handleFooWhenItIsInteger();
           //EDIT1
       }
       else
       {
           foo = new Foo<String>();
           //EDIT1
           handleFooWhenItIsString();
           //EDIT1
       }
}

assume that I do some integer work in function 'handleFooWhenItIsInteger()' and with some string in another one.

Is defining 'foo' like above OK?

Upvotes: 0

Views: 83

Answers (5)

piet.t
piet.t

Reputation: 11921

As the others already said: it will compile with some warnings, but most probably it will behave just the same as

public class MyClass
{
    Foo foo;
    public MyClass(int x)
    {
       foo = new Foo();
    }
}

Why is that?

  • Java generics only enable compile-time-checks, at runtime all information you gave using generics is lost.
  • The compiler only knows what is declared - so when using the identifier foo it only knows it's a Foo but has no information on its generic type
  • While using new Foo<String>() might make a bit of a difference while invoking the constructor after the assignment to foo the compiler will no longer know about it.

Upvotes: 0

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44087

This will compile, however, the use of raw types such as

Foo foo;

for your generic type Foo<T> is discouraged. Raw types are only supported for legacy reasons, i.e. compatibility to code written before Java 5 where generics were introduced.

In order to describe any generic Foo you should rather write Foo<?> which describes an instance of Foo of any generic type. The compiler will then check for you that you do not invoke any non-type safe methods on these instances later in your code as for example in your case, the instance could reference a Foo<Integer> or a Foo<String>. Thanks to using the wildcard type Foo<?>, you can reference both using the same variable but you cannot longer make an assumption on the actual generic type of the referenced instance.

Technically, there is no big difference between using Foo or Foo<?>. However, using the former, the compiler will generate a warning for using a raw type. The compiler cannot know for sure that you did not forget to add the generic type arguments and only use the raw type accidentally. This is why you should spend the few characters to always add <?> if you require a wildcard reference.

Upvotes: 1

Elliott Frisch
Elliott Frisch

Reputation: 201537

Is defining 'foo' like above OK?

No. It's a raw type, this

Foo foo;

isn't generic because of the raw-type. It's equivalent to

Foo<Object> foo;

You should have the type of Foo it is. So something like

Foo<Integer> foo;

or maybe

public class MyClass<T> {
  Foo<T> foo;

Upvotes: 0

ortis
ortis

Reputation: 2223

This will work but will generate warning because the declaration of Foo foo is not parametrized. Then, you will be in charge to insure that all Foo interaction are consistent accross your code. Otherwise, you might face some ClassCastException

Upvotes: 0

SANN3
SANN3

Reputation: 10119

Ya ok. But foo is generic, you cannot know what type it is when you use outside the constructor.

Upvotes: 0

Related Questions