简体   繁体   English

Java通用类型实例化

[英]Java Generic type instantiation

There are many questions like this, but none of them seem to answer my question specifically. 像这样的问题很多,但是似乎没有一个问题可以专门回答我的问题。

How do you instantiate a new T? 您如何实例化新的T?

I have a generic method, I need to return a new instance of the type in the type parameter. 我有一个通用方法,我需要在type参数中返回该类型的新实例。 Here is my code... 这是我的代码...

class MyClass {

  public static MyClass fromInputStream( InputStream input ) throws IOException {

    // do some stuff, and return a new MyClass.

  }
}

Then in a seperate class I have a generic method like so... 然后在一个单独的类中,我有一个像这样的通用方法...

class SomeOtherClass {

  public <T extends MyClass>download(URL url) throws IOException {

    URLConnection conn = url.openConnection();

    return T.fromInputStream( conn.getInputStream() );

  }
}

I also tried the following... 我也尝试了以下...

class SomeOtherClass {

  public <T extends MyClass>download(URL url) throws IOException {

    URLConnection conn = url.openConnection();

    return new T( conn.getInputStream() ); // Note my MyClass constructor takes an InputStream...

  }
}

But neither permutation of the above will compile! 但是以上两种排列都不会编译! The error is: 错误是:

File: {...}/SomeOtherClass.java
Error: Cannot find symbol
symbol : class fromInputStream
location : class MyClass

Any suggestions would be appreciated! 任何建议,将不胜感激!

I think a common approach is to require the class of type T to be passed in like so: 我认为一种常见的方法是要求像这样传递T类型的类:

class SomeOtherClass {

  public <T extends MyClass> T download(Class<T> clazz, URL url) throws IOException {

    URLConnection conn = url.openConnection();

    return clazz.getConstructor(InputStream.class).newInstance(conn.getInputStream() ); // Note my MyClass constructor takes an InputStream...

  }
}

Other than passing in a Class object and using reflection like in johncarl's answer , you could use a generic factory: 除了传递Class对象并像johncarl的答案中那样使用反射之外 ,还可以使用泛型工厂:

public abstract class InputStreamFactory<T> {

    public T make(InputStream inputStream) throws IOException;
}

And revise download : 并修改download

public <T extends MyClass> T download(URL url, InputStreamFactory<? extends T> factory) throws IOException {

    URLConnection conn = url.openConnection();

    return factory.make(conn.getInputStream());
}

Each MyClass derivation could provide its own factory implementation: 每个MyClass派生都可以提供自己的工厂实现:

public class MySubClass extends MyClass {

    public static final InputStreamFactory<MySubClass> FACTORY =
            new InputStreamFactory<MySubClass>() {
                @Override
                public MySubClass make(InputStream inputStream) throws IOException {
                    return new MySubClass(inputStream); //assuming this constructor exists
                }
            };
}

And the caller could reference it: 呼叫者可以引用它:

MySubClass downloaded = new SomeOtherClass().download(url, MySubClass.FACTORY);

You no need to use parameter here to call method. 您无需在此处使用参数来调用方法。 Because you have static method, will be enough to access fromInputStream method directly from MyClass, I mean: 因为您有静态方法,足以直接从MyClass访问fromInputStream方法,我的意思是:

return MyClass.fromInputStream( conn.getInputStream() );

Hope it will help you 希望对您有帮助

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

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