Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无法实例化类型T_Java_Hadoop_Generics - Fatal编程技术网

Java 无法实例化类型T

Java 无法实例化类型T,java,hadoop,generics,Java,Hadoop,Generics,我有一门课看起来像这样 public class LegionInputFormat extends FileInputFormat<NullWritable, LegionRecord> { @Override public RecordReader<NullWritable, LegionRecord> createRecordReader(InputSplit split, TaskAttemptContex

我有一门课看起来像这样

public class LegionInputFormat
        extends FileInputFormat<NullWritable, LegionRecord> {

    @Override
    public RecordReader<NullWritable, LegionRecord>
            createRecordReader(InputSplit split, TaskAttemptContext context) {

        /* Skipped code for getting recordDelimiterBytes */

        return new LegionRecordReader(recordDelimiterBytes);
    }
}
公共类LegionInputFormat
扩展FileInputFormat{
@凌驾
公共记录阅读器
createRecordReader(InputSplit拆分,TaskAttemptContext上下文){
/*已跳过获取recordDelimiterBytes的代码*/
返回新的军团记录阅读器(recordDelimiterBytes);
}
}
我希望使用泛型类型,以便它可以返回用户指定的任何类型的RecordReader,如下所示:

public class LegionInputFormat<T extends RecordReader<NullWritable, LegionRecord>>
        extends FileInputFormat<NullWritable, LegionRecord> {

    @Override
    public RecordReader<NullWritable, LegionRecord>
            createRecordReader(InputSplit split, TaskAttemptContext context) {

        /* Skipped code for getting recordDelimiterBytes */

        return new T(recordDelimiterBytes);
    }
}
公共类LegionInputFormat
扩展FileInputFormat{
@凌驾
公共记录阅读器
createRecordReader(InputSplit拆分,TaskAttemptContext上下文){
/*已跳过获取recordDelimiterBytes的代码*/
返回新的T(recordDelimiterBytes);
}
}
正如文章标题所暗示的,从其他堆栈交换文章中,我被告知我“无法实例化类型T”。我收集到这是不可能的,因为泛型是如何工作的。我无法收集到的是关于为什么会这样的直观解释。我通过理解学习得最好,所以如果有人能提供,这将非常有帮助

我还对实现我希望在这里做的事情的最佳实践感兴趣。
LegionInputFormat
的构造函数是否应该接受
RecordReader
类,存储该类,然后稍后引用它以创建新实例?还是有更好的解决方案

(另外的背景——这里的背景是Hadoop,但我怀疑它是否重要。我是一位相当有成就的数据科学家,但我对Java非常陌生。)

正如文章标题所暗示的,从其他堆栈交换文章中,我被告知我“无法实例化类型T”。我收集到这是不可能的,因为泛型是如何工作的

这是因为Java中的泛型纯粹是编译时特性;编译器丢弃了泛型(称为“”),因此在运行时,没有类型变量
T
,因此不能执行
newt(…)

在Java中,可以通过将
对象传递给需要创建
T
实例的方法,然后通过创建实例来实现这一点

正如文章标题所暗示的,从其他堆栈交换文章中,我被告知我“无法实例化类型T”。我收集到这是不可能的,因为泛型是如何工作的

这是因为Java中的泛型纯粹是编译时特性;编译器丢弃了泛型(称为“”),因此在运行时,没有类型变量
T
,因此不能执行
newt(…)


在Java中,可以通过将
对象传递给需要创建
T
实例的方法,然后通过创建实例来实现这一点。

在第二个代码示例中,编译器无法知道
T
是否有接受
recordDelimiterBytes
作为参数的构造函数。这是因为每个类都是一个独立的编译单元,所以当编译
LegionInputFormat
时,编译器只知道
T
是一个
RecordReader
。它不知道哪些具体类型用于
t
,它必须假设以后有人可以加入任何扩展
RecordReader
的类。我们可以使用
extends
告诉编译器一些关于
T
的信息,但是在Java中,我们无法指定
T
有一个构造函数
T(byte[])
(或者无论
recordDelimiterBytes
的类型是什么)

我已经多次使用下面的解决方案,尽管它需要创建子类,但我对它非常满意。这项工作仍在泛型类中。现在宣布为抽象:

public abstract class InputFormat<T extends RecordReader<NullWritable, LegionRecord>>
        extends FileInputFormat<NullWritable, LegionRecord> {

    private byte[] recordDelimiterBytes;

    @Override
    public RecordReader<NullWritable, LegionRecord> createRecordReader(InputSplit split, TaskAttemptContext context) {

        /* Skipped code for getting recordDelimiterBytes */

        return constructRecordReader(recordDelimiterBytes);
    }

    // factory method for T objects
    protected abstract RecordReader<NullWritable, LegionRecord> constructRecordReader(byte[] recordDelimiterBytes);
}
然后,您只需在实施过程中跟进:

protected LegionRecordReader constructRecordReader(byte[] recordDelimiterBytes) {

在这种情况下,它甚至会缩短几个字符。另一方面,在您的例子中,您似乎不需要它,因此您可能更喜欢使用较弱的返回类型
RecordReader

,在第二个代码示例中,编译器无法知道
t
是否有接受
recordDelimiterBytes
作为参数的构造函数。这是因为每个类都是一个独立的编译单元,所以当编译
LegionInputFormat
时,编译器只知道
T
是一个
RecordReader
。它不知道哪些具体类型用于
t
,它必须假设以后有人可以加入任何扩展
RecordReader
的类。我们可以使用
extends
告诉编译器一些关于
T
的信息,但是在Java中,我们无法指定
T
有一个构造函数
T(byte[])
(或者无论
recordDelimiterBytes
的类型是什么)

我已经多次使用下面的解决方案,尽管它需要创建子类,但我对它非常满意。这项工作仍在泛型类中。现在宣布为抽象:

public abstract class InputFormat<T extends RecordReader<NullWritable, LegionRecord>>
        extends FileInputFormat<NullWritable, LegionRecord> {

    private byte[] recordDelimiterBytes;

    @Override
    public RecordReader<NullWritable, LegionRecord> createRecordReader(InputSplit split, TaskAttemptContext context) {

        /* Skipped code for getting recordDelimiterBytes */

        return constructRecordReader(recordDelimiterBytes);
    }

    // factory method for T objects
    protected abstract RecordReader<NullWritable, LegionRecord> constructRecordReader(byte[] recordDelimiterBytes);
}
然后,您只需在实施过程中跟进:

protected LegionRecordReader constructRecordReader(byte[] recordDelimiterBytes) {

在这种情况下,它甚至会缩短几个字符。另一方面,在您的情况下,您似乎不需要它,因此您可能更喜欢使用较弱的返回类型
RecordReader

。不过,我不确定为什么这会阻止这种情况发生?因此,在编译时,
T
LegionRecordReader
或任何其他
RecordReader
类I指定的。。。为什么这会阻止
returnnewt
在编译时变成
returnnewlegionrecordreader
?在编译时,
T
java.lang.Object
取代。不是
LegionRecordReader
。编译器无法知道
T
是否有一个接受
recordDelimiterBytes
作为参数的构造函数