Generics and creating new objects
Assume this class:
class Yatta<T>
{
public Yatta()
{
T t =new T();
}
}
When compiling I get "unexpected type" refering to the "T" in "new T()". Why isn't this allowed? Is there any way of doing something similar without creating a huge chain of factories for each type?
[538 byte] By [
Magosa] at [2007-10-3 3:49:12]

you cannot because you know nothing about T... can you garantee that it have a no-args constructor?read the generics tutorial... it will be far more helpful: http://java.sun.com/docs/books/tutorial/java/generics/index.html(special attention to bounded types)
I'm going with a clone-like structure instead. Basically it's a container based on ArrayList but that performs a deep copy instead of ArrayList's shallow copy. Component is the superclass for all items that can be added to the container (only one type per container of course). It has a method duplicate() that works pretty much like clone() and is overloaded in each subclass.
Anyway on the row I've marked below I get a warning ".java uses unchecked or unsafe operations". It's a downcast but is there a way of removing this warning (code-wise, not adding some flag to skip certain warnings)?
import java.util.*;
public class Container<Type extends Component> extends ArrayList<Type>
{
public Container()
{
//Empty
}
public Container(Container<Type> object)
{
ListIterator<Type> i = object.listIterator();
while(i.hasNext())
{
Type t = i.next();
Component c = t.duplicate();
Type tt = (Type)c; //<- XXX
add(tt);
//add((Type)i.next().duplicate());
}
}
}
Magosa at 2007-7-14 21:46:21 >

Please use single letters for type parameters. Doing what you've done with "Type" makes reading the code difficult...
Since duplicate() is declared in Component I assume it is declared to return Component. How can the compiler possibly know that it is going to return a more specific type? It can't. (Well... you can tell it... see below)
Because of what I wrote in the first paragraph, it's not immediately obvious that Type is a type parameter, but it is, and casting to a type parameter doesn't get you anywhere. From this code and your original post, you appear to be treating Java Generics like C++ templates. They are not the same. In particular, Generics are implemented using a technique called erasure which means that the type parameter information is not present in the compiled class files. The practical upshot of this is that the cast in the line you highlight is in fact a cast to Component (since that is the upper bound of Type) and this cast is useless because we already know the c is a Component. So the compiler is correctly warning you that the typecast will not actually perform the check that you want it to.
(In fact, if you try this in Eclipse, you get a better warning: "Type safety: The cast from Component to T is actually checking against the erased type Component")
So... how to fix this...?
Well, you need to make the return type of duplicate() change depending on the concrete implementation. You could do this by parameterising Component thus:
public interface Component<T extends Component><T>> {
// ...
public T duplicate();
// ...
}
Now, every use of Component will need to be parameterised. In the case of the code you have below, you'll need:
public class Container<T extends Component><T>> extends ArrayList<T> {
public Container() {
//Empty
// Why write it then? Get rid of it.
}
public Container(Container<T> object) {
Iterator<T> i = object.iterator(); // don't need ListIterator here
while(i.hasNext()) {
add(i.next().duplicate());
}
}
}
and every implementation of Component needs to look like this:
public static class Something implements Component<Something> {
public Something duplicate() { // note the return type
return null; // or something more useful!
}
}
Hope that helps.
(PS 'tabs' are the work of satan and should never be found in source code)
And while you're at it, you can use the new for-each language construct if you feel the urge...
public class Container<T extends Component><T>> extends ArrayList<T> {
public Container(Container<T> object) {
for (T t: object) {
add(t.duplicate());
}
}
}
>public Container() {
>//Empty
>// Why write it then? Get rid of it.
> }
Because then you can more easily use stuff like "Open method hierarchy" in a good IDE!
Eh?!
1) There is no "method hierarchy" for constructors as they are not inherited or, therefore, overridden
2) Writing code just to support your IDE is a bit tail-wagging-the-dog, no? You add a bunch of redundant code to help your IDE, then I add a bunch for my (different) IDE, etc., then where are we?
> Eh?!
>
> 1) There is no "method hierarchy" for constructors as
> they are not inherited or, therefore, overridden
I meant "method call hierarchy" - it means when my caret is over the constructor, CTRL-ALT-H and I see all callers of the constructor.
Anyway, I was being glib but in my opinion explicitly creating a default constructor is a good idea for the following reason: you define its visibility. You may be creating a class ostensibly for being extended (so the constructor should be protected), or it may be a static singleton and you want the constructor to be explicitly private. Declaring a constructor, even the default public one, shows that you mean it to exist and that it's not existing because you forgot to "un-exist" it. Anyway, it's not really a big deal, I agree.
> 2) Writing code just to support your IDE is a bit tail-wagging-the-dog, no?
> You add a bunch of redundant code to help your IDE, then I add a bunch
> for my (different) IDE, etc., then where are we?
Yup. See previous admittance of glibness.
