将通用类型实现为语言

时间:2015-09-28 08:03:03

标签: oop generics types instantiation

我想在语言中添加对泛型的支持,但在此之前,我需要更清楚地了解内部的泛型。

我目前的理解是实例化类:

class ArrayList<T>
{
    public int add(T object)
    {
        // ...
    }
}

创建一个实例,其中T上的参数类型add必须与new ArrayList<T>()上的T类型参数相同,其中true === (new ArrayList<Date>() instanceof ArrayList) 是真实类型。

实现这一点似乎很简单,但仅适用于此用例。当它需要支持内省时,它就变成了一个更复杂的概念。例如,我不会说:

true === (new ArrayList<Date>() instanceof ArrayList<Date>)

但我会说:

ArrayList<Date>

我的问题是,当使用ArrayList<T>作为类型引用时,它是一个派生自$list = new ArrayList<Date>(); 的类型,还是它本身就是一个类,例如:

class ArrayList
{
    public int add(Date $object)
    {
        // ...
    }
}

一个实例:

ArrayList<T>

或者它是T Date private void addAttachments( Redemption.RDOMail sourceMail , ref Redemption.RDOMail targetMail ) { foreach (Redemption.RDOAttachment attachment in sourceMail.Attachments) { // Saving attachment files from source mail on local disk attachment.SaveAsFile(/*File Path*/); // adding attachment to target mail from saved location //At this point, target mail has the attachment count incremented targetMail.Attachments.Add(/*File PAth*/ + attachment.DisplayName); // deleting file, saved on local disk File.Delete(/*File Path + attachment.DisplayName*/); } targetMail.Save(); // when the mail item is being displayed, the added attachment with the *.EXE, //or all the other attachment extentions which are blocked from viewing by outlook is gone. // This does not happen for other attachment files targetMail.Display(); } 的实例吗?

2 个答案:

答案 0 :(得分:1)

Java泛型和C ++模板乍一看看起来很相似,但是以相反的方式实现。正如Steffen Kreutz在评论中所说,java使用类型擦除作为其泛型。类型擦除意味着在编译时,java控制对泛型类的访问,但在运行时,所有类型信息都消失了,ArrayList<Date>ArrayList<Integer>共享完全相同代码。

这与模板完全不同。在模板中,每个具体类都是在编译时实现的,因此(在C ++中)vector<double>vector<char>是两个不同的类,它们的编译代码将是不同的,因为一个将采用双参数,而另一个将采用字符,它们不会在堆栈中以相同的方式传递。

如果你需要一个泛型类来知道它可以接受的类型,你必须明确地使用一个属性来保存它。例如:

class MyGen<T> {
    class<T> myClazz;

    MyGen(class<T> clazz) {
        myClass = clazz;
    }
    ...
}

然后你可以在myClazz上使用反射,因为它是一个在运行时可用的真正的类对象,而T只能在编译时使用,不能通过反射使用。

答案 1 :(得分:0)

泛型只是编译时的助手。如果我们没有泛型,我们会编写这样的代码:

ArrayList list = new ArrayList();
list.add(new Date());
Date date = (Date) list.get(0);

已经引入了泛型来删除必要的强制转换,我们现在可以写:

ArrayList<Date> list = new ArrayList<>();
list.add(new Date());
Date date = list.get(0);

您可能认为ArrayList类在内部管理Date数组,但事实上 它管理一个Object的数组。编译器会在您访问元素的位置插入缺少的强制转换。

使用泛型具有另一个好处。编译器可以检测您是否进行了无效的转换。因此不可能写出这样的东西:

ArrayList<Date> list = new ArrayList<>();
list.add(new Date());
String date = list.get(0);

您可以验证具有不同类型参数的ArrayList是否仍然使用new ArrayList<String>().getClass().equals(new ArrayList<Date>().getClass())编译到同一个类。

查看Oracle Java Documentation about type erasure