Calling constructor of a generic type

后端 未结 6 1700
借酒劲吻你
借酒劲吻你 2020-12-10 12:48

If I have an abstract class like this:

public abstract class Item
{
    private Integer value;
    public Item()
    {
        value=new Integer(0);
    }
           


        
相关标签:
6条回答
  • 2020-12-10 13:05

    It's impossible to use T to call a constructor because if it would be possible than after a compilation you would get the code like this:

    public class Box{
        Object item;
        public Box(){
            item = new Object();
        }
    }
    

    So if you would use this code and pass some object than you expect that there is the constructor of some specific type is called, but instead you get the Object constructor.

    0 讨论(0)
  • 2020-12-10 13:07

    This is because Java uses erasure to implement generics, see this:

    • http://en.wikipedia.org/wiki/Generics_in_Java#Problems_with_type_erasure

    To quote the relevant parts from the above Wikipedia article:

    Generics are checked at compile-time for type-correctness. The generic type information is then removed in a process called type erasure.

    As a result of type erasure, type parameters cannot be determined at run-time.

    Consequently, instantiating a Java class of a parameterized type is impossible because instantiation requires a call to a constructor, which is unavailable if the type is unknown.

    You can go around this by actually providing the class yourself. This is well explained here:

    • Create instance of generic type in Java?
    0 讨论(0)
  • 2020-12-10 13:14

    T is an alias for the actual type your class will handle, for example if you instantiate Box<Item> then T is really just an alias for Item. As you declare T extends Item then you know that T will have at least the same interface as Item, so you can treat it like one.

    I think what you really want to do is not instantiate the item field in Box, but instead implement a couple of methods to let you manipulate that field.

    public class Box<T extends Item> {
        private T item;
    
        public T getItem() {
            return this.item;
        }
    
        public void setItem(T item) {
            return this.item = item;
        }
    }
    
    0 讨论(0)
  • 2020-12-10 13:20

    There is no way to use the Java type system to enforce that a class hierarchy has a uniform signature for the constructors of its subclasses.

    Consider:

    public class ColorPencil extends Pencil
    {
        private Color color;
    
        public ColorPencil(Color color)
        {
            super();
            this.color=color;
        }   
    }
    

    This makes ColorPencil a valid T (it extends Item). However, there is no no-arg constructor for this type. Hence, T() is nonsensical.

    To do what you want, you need to use reflection. You can't benefit from compile-time error checking.

    0 讨论(0)
  • 2020-12-10 13:22

    You can place an abstract method so that the implementing class can determine how to construct the new object.

    public abstract T constructT();
    

    and instead of calling

    T t = new T()
    

    you would call

    T t = constructT();
    

    On your implementing call it would be created as:

    new Box<Integer>() {
        public Integer constructT(){ return new Integer(); }
    }
    
    0 讨论(0)
  • 2020-12-10 13:26

    Because at runtime the type of T is unknown.

    0 讨论(0)
提交回复
热议问题