使用泛型实现Java接口

3

我正在编写一些Java代码,想在我的主类Array中编写方法。该类实现了ImplementableClass接口,前者继承自Iterable接口。Array类具有一个类型。

ImplementableClass.java:

public interface ImplementableClass<E> extends Iterable<E>{

    public void insertObject(E obj);

    public E removeObj(E obj);

}

Main.java:

public class Array<Integer> implements ImplementableClass<E>{
    public void insertObject(E obj){

    }

    public E removeLastObject(E obj){

    }

    //... main method and others below...
}

我对上面两个文件中的代码有一些疑问。

根据Java文档,Iterable是类型E(泛型值)。据我所知,接口只是“蓝图”,其中必须在“实现”它们的类中使用方法。从基本的角度来看,这里不应该有任何变量。话虽如此,正如您所看到的,我确实在我的ImplementableClass中声明了方法,并在Main中使用。因此,我有几个问题:

  1. 当我在我的Array类中声明ImplementableClass类的方法时,这会“覆盖”ImplementableClass类的方法,对吗?

  2. 由于“E obj”是两个方法中的参数,我在我的Array类中声明方法时它们必须相同吗?我应该传递什么给这些方法?“E obj”是什么意思?

  3. 我想创建一个可以容纳类型为E的对象的数组。这意味着每当我实例化一个新对象时-> Array<Integer> theArray = new Array<Integer> 我可以在theArray实例上调用我在Array类中拥有的方法,对吗?(例如theArray.removeLastObject())我应该传递什么参数?

  4. 为什么在这种情况下使用Iterable<E>会有用?


“public class Array implements ImplementableClass<Integer>{” 这样写不是更合理吗? - MadProgrammer
2个回答

4

当在我的Array类中声明实现ImplementableClass类的方法时,这会“覆盖”我的ImplementableClass类的方法吗?

是的(虽然从技术上讲,在接口中没有功能可以覆盖,但您可以使用@Override来表示您正在覆盖它)。

由于“E obj”是两个方法中的参数,因此我在Array类中声明我的方法时它们必须相同吗?我应该传递什么给这些方法?“E obj”是什么意思?

它们需要与您实现接口时指定的通用类型相同。E obj表示您声明了一个名为obj的参数,其通用类型为E。 这意味着您需要定义以该特定类型作为参数的方法。

不过,更合理的做法是在声明中定义接口的通用类型,例如:

public class ArrayClass implements ImplementableClass<Integer>

因此,您可以拥有像以下这样的方法:

public void insertObject(Integer obj) {}

public Integer removeObj(Integer obj) {}

否则,您可以将Array类变为通用类,并将通用类型的规范留给调用者:
public class ArrayClass<E> implements ImplementableClass<E>

我想创建一个可以容纳类型为 E 的对象的数组。这意味着每当我实例化新的对象 -> Array theArray = new Array,我就可以在 theArray 实例上调用我在 Array 类中拥有的方法,对吗?(即 theArray.removeLastObject())我应该传递什么参数?
为了做到这一点,您需要使您的 Array 类成为通用类,如上所示。您传递的参数将是您创建数组时指定的相同类型(在您的示例中为 Integer)。
在这种情况下,Iterable 有什么用处?
Iterable 可以使用数组的迭代器功能和增强的 foreach 语法(for (Object o : someObjectArray) {...})。
另外,我建议不要将您的 Array 类命名为 Array... 可能考虑利用已经存在的 Iterable 类来构建您正在做的事情,但这看起来像一个学习练习,所以请继续努力。
希望对您有所帮助。

谢谢您提供如此详细的回答。当我按照您的建议使我的类变成泛型 "public class Array<E> implements ImplementableClass<E>" 时,Eclipse会抱怨说:"E无法解析为一种类型"。您知道为什么会发生这种情况吗?谢谢! - J Tarantino
@JTarantino 你可能在某个地方有一个悬挂的类型参数,它在编译时从未被命名为一个类型。这种情况最常见于声明无法由调用者创建对象时命名的泛型类型,通常是由于类型冲突或拼写错误引起的。 - Ryan J
谢谢!又是一个愚蠢的问题... <E> 泛型类型到底是什么?它是 Java 定义的泛型类型,还是我随意选择 <E> 作为泛型类型?再次感谢您的帮助! - J Tarantino
@JTarantino <E> 是一种类型参数,用于标识一个尚未知晓但在创建类的引用后将会确定的类型。E 是用于标识泛型类的符号的任意选择。通常情况下,您会经常看到 TE 用于这些参数,但这只是大多数人使用的约定。 - Ryan J
谢谢你的帮助!你解决了我关于这个问题的所有疑问。也许你可以帮我解决这个问题?http://stackoverflow.com/questions/28597396/default-constructor-issue-when-creating-an-array-java - J Tarantino

0
  1. 实际上发生的是,您正在实现接口,而不是重写它。因为接口(在Java <=7中)没有实现,所以您实际上没有什么可以重写的。您可以使用@Override注释表示您正在实现从接口继承的方法

  2. 在您的第二个类中错过了泛型。如果您确实想要它是通用的(即,它可以绑定到任何对象),那么您需要这个声明:

    public class Array<E> implements ImplementableClass<E>
    

    <E>称为类型参数,它应用于类级别,意味着类中的任何非静态方法或字段都可以使用它。

    E obj表示您愿意接受作为参数提供的任何类型的对象。如果您声明了Array<Integer> intArray = new Array<>();,那么E obj将在内部转换为Integer obj。与泛型相关的复杂操作有相当多;最好阅读相关文献。

  3. 明确指定您想要使用的数据结构{{link3:数组和泛型不太搭配。}}如果您正在创建通用对象数组(例如,E[] backingStore),那么创建通用数组将是要考虑的一个因素。

    老实说,我建议您改用List

  4. Iterable表示您拥有的对象可以使用增强型for语句进行迭代。为什么您要这样做取决于您的判断,但这就是您想要使用特定接口的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接