0

Possible Duplicate:
Java Generics: Cannot cast List<SubClass> to List<SuperClass>?

I want to create function on some base class, that create it inheritance classes.

I have try this:

class BaseFormat
{
    // Some variables

    public BaseFormat(string txt)
    {
        // Do something
    }

    public static <T> ArrayList<T extends BaseFormat> getTextFormat(String[] txt)
    {
        ArrayList<T> list = new ArrayList<T>();
        for (int i = 0; i < txt.length; i++)
        {
            list.add(new T(txt[i])); // ERROR
        }
        return list;
    }
}

class FooFormat extends BaseFormat
{
    // Some variables

    public FooFormat (string txt)
    {
        // Do something
    }
}

And this:

class BaseFormat
{
    // Some variables

    public BaseFormat(string txt)
    {
        // Do something
    }

    public static ArrayList<BaseFormat> getTextFormat(String[] txt)
    {
        ArrayList<T> list = new ArrayList<T>();
        for (int i = 0; i < txt.length; i++)
        {
            list.add(new BaseFormat(txt[i]));
        }
        return list;
    }
}

But when I try to cast the array I receive an error. This is my code:

String[] txts = ...; // Some texts
ArrayList<FooFormat> list = (ArrayList<FooFormat>) BaseFormat.getTextFormat(txts); // Casting ERROR

So how can I do it, but still keep it generic?

Community
  • 1
  • 1
nrofis
  • 8,975
  • 14
  • 58
  • 113
  • What do you want to do with `ArrayList list`? – Bhesh Gurung Oct 15 '12 at 17:42
  • You cannot create an instance of a generic type. Some options might be to have subclasses register with the base class or provide an instance of `Class>` from which you could use reflection to call a constructor. – John B Oct 15 '12 at 17:43
  • FooFormat is-a BaseFormat but not vice-versa. – Bhesh Gurung Oct 15 '12 at 17:45
  • 1
    You cannot cast from `List` to `List` which of course makes sense because your code is creating an instance of `BaseFormat`, how could that be treated as a `FooFormat`? – John B Oct 15 '12 at 17:45
  • I have methods in FooFormat, and I know that strings should be `FooFormat` – nrofis Oct 15 '12 at 17:46
  • I thought that if FooFormat extends BaseFormat it shold work – nrofis Oct 15 '12 at 17:48
  • You should familiarize yourself with the [PECS acronym](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs). – Brian Oct 15 '12 at 17:49

4 Answers4

0

try doing

  ArrayList<BaseFormat> list = (ArrayList<BaseFormat>) BaseFormat.getTextFormat(txts);

Then on iterating you can down cast the items to FooFormat with check of instanceOf operator

saum22
  • 884
  • 12
  • 28
0

Are you trying to do something as follows

class BaseFormat { }

class FooFormat extends BaseFormat { }

class FormatUtils {
    public static <T extends BaseFormat> List<T> getTextFormat(String[] txt, Class<T> clazz) {
        List<T> list = new ArrayList<T>();
        //... 
                T t = clazz.newInstance(); //create instance using reflection
                //...
        return list;
    }
}

And do

List<FooFormat> list = FormatUtils.getTextFormat(new String[]{}, FooFormat.class);
Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
0

So, you are mixing generics, which allow dynamic typing, with inheritance, which allows overriding methods. What you really want is to separate creating the wrapped string from creating the list.

class BaseFormat
{
  // derived classes override this method to provide their own implementations
  public abstract BaseFormat wrapText(String[] txt);

  public ArrayList<? extends BaseFormat> getTextFormat(String[] txt)
  {
    ArrayList<? extends BaseFormat> list = new ArrayList<BaseFormat>();
    for (int i = 0; i < txt.length; i++)
    {
        list.add(wrapText(txt);
    }
    return list;
  }
}
Zagrev
  • 2,000
  • 11
  • 8
  • `new ArrayList extends BaseFormat>();` makes errors. And still, I cant cast from `BaseFormat` to `FooFormat` – nrofis Oct 15 '12 at 17:54
  • Fixed the constructor. If you are using polymorhism, you don't need to know its a FooFormat. The methods you call on the object will perform the FooFormat version, not the BaseFormat version. – Zagrev Oct 15 '12 at 18:03
  • I see, but I need it static. Can I do it with static way? – nrofis Oct 15 '12 at 18:04
  • So, why does it need to be static? If it's static, how to you plan on creating the new, derived classes? – Zagrev Oct 15 '12 at 18:36
  • So, basically, I think your design is broken. You should not *need* static methods. – Zagrev Oct 15 '12 at 18:39
  • This method create instance of Format classes. I cant just call for it constructor. This method act like factory. – nrofis Oct 15 '12 at 18:47
0

You would have to pass the type in as a parameter to the static method, and then probably use reflection to invoke Class.newInstance. Type erasure means you will not have a concrete type T after compilation, so that is why you can't compile new T(...)

Kevin Welker
  • 7,719
  • 1
  • 40
  • 56