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

Jas*_*son 9 java generics methods function

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

C++

    float* myFloat = CollectionClass.ptr<float>();
    int*   myInt   = CollectionClass.ptr<int>();
Run Code Online (Sandbox Code Playgroud)

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>();
Run Code Online (Sandbox Code Playgroud)

new*_*cct 19

使用签名声明方法完全没问题public <T> T getDate().

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

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

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

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

Date myDate = (Date)getDate();
Run Code Online (Sandbox Code Playgroud)

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

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

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


Jon*_*eet 10

好的,现在通过编辑来明确代码是有条件的T......

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

public <T> T getDate(Class<T> clazz)
{
    // Now use clazz to work out what to do
}
Run Code Online (Sandbox Code Playgroud)

......但你不能做任何依赖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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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