繁体   English   中英

在Java中使用Generic返回类型调用方法

[英]Method call with Generic return type in Java

在C ++中,您可以在参数中指定函数的返回类型,例如:

C ++

    float* myFloat = CollectionClass.ptr<float>();
    int*   myInt   = CollectionClass.ptr<int>();

Java中是否有等价物来指定返回类型而不添加额外的类args?

Java的

    //This doesn't work (due to type erasure) 
    public <T> T getDate() 
    {
        if (T instanceof Date)
            return new Date();
        if (T instanceof Calendar)
            return new Calendar();
    }

    Date myDate = getDate<Date>();

使用签名public <T> T getDate()声明一个方法是完全正常的。

但是,无法实现返回所需内容的方法。 方法在运行时的作用不能仅依赖于它的类型参数,因为它不知道它的类型参数。

为了获得对此的直觉,请认识到使用泛型编写的任何代码也可以在不使用泛型的情况下等效编写,只需删除泛型参数并在适当的位置插入强制转换。 这就是“类型擦除”的含义。

因此,要想看看你的方法是否可以在泛型中使用,只需问一下,如果没有泛型,你会怎么做:

public Object getDate() 
{
    // what would you do here?
}

Date myDate = (Date)getDate();

如果没有Generics就无法做到,那么你也无法使用Generics。

C ++模板完全不同。 对于模板化函数和类,C ++模板为与其一起使用的每个类型参数生成函数或类的“单独副本”。 即编译器获取模板化代码并将其“复制并粘贴”到多个版本中,每个版本都是独立的。 因此,代码的每个副本都特定于某个类型参数,因此可以在运行时使用该类型。

这就是为什么C ++模板化代码需要以源代码形式提供才能使用它 - 没有“编译”模板这样的东西。 但是,在Java中,可以使用编译的泛型类。 Java中的通用类和方法不会假设它们可以使用的类型。

好的,现在通过编辑清楚地表明代码是以T为条件的......

不,在Java中没有任何简单的方法可以实现这一功能 - 由于类型擦除,正如您的问题所提到的那样。 你可以传入Class<T>

public <T> T getDate(Class<T> clazz)
{
    // Now use clazz to work out what to do
}

...但是你不能做任何依赖于T本身在执行时的“价值”的事情 ,因为那是根本不知道的。 不幸的是,遗传学在Java中有些贫血:(


编辑:在编辑之前使代码以T为条件...

这只是以不同方式指定类型参数的问题:

import java.util.Date;

class Test {

    public static <T> T getDate() {
        return (T) new Date();
    }

    public <T> T getDateInstanceMethod() {
        return (T) new Date();
    }

    public static void main (String [] args) {
        Date date = Test.<Date>getDate();

        // Compiles fine, but is obviously bogus.
        String string = Test.<String>getDate();

        // And specifying a type argument for an instance method
        Test test = new Test();
        date = test.<Date>getDate();
    }
}

我总是更喜欢“在常规参数之前放置类型参数”的方法,但是我们去...

编辑:正如rgettman指出的那样,类型推断无论如何都会为你做正确的事情,因此在很多情况下你实际上并不需要指定类型参数。 有时你会这样做。

使用Arrays.asList ,有时需要指定返回类型。 Java试图根据所有参数的常见超类来“缩小”返回类型,但有时您需要特定类型。 例如,

List<Number> list = Arrays.asList(1, 2, 3);

这里, Arrays.asList返回List<Integer>并且您得到编译器错误。 要使其返回List<Number> ,必须指定泛型类型。

List<Number> list = Arrays.<Number>asList(1, 2, 3);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM