我想知道在泛型类或方法中使用接口(interface)(或父类(super class)型)与使用带边界的泛型方法(T 扩展接口(interface))有什么区别。
假设我有两个实现类和接口(interface)类(简单示例):
public interface MeasurableDistance {
public Point getPosition();
}
public class Person implements MeasurableDistance {
private Point position;
public Point getPosition() {
return position;
}
}
public class House implements MeasurableDistance {
private Point position;
public Point getPosition() {
return position;
}
}
1) 以下列方式编写方法有什么区别:
public int computeDistance(MeasurableDistance a, MeasurableDistance b) {
Point a = a.getPosition();
Point b = b.getPosition();
//compute distance
return distance,
}
和类似的东西
public <T extends MeasurableDistance, S extends MeasurableDistance> int computeDistance(T a, S b) {
Point a = a.getPosition();
Point b = b.getPosition();
//compute distance
return distance,
}
2) 如果我想要一个类来保存一个 MeasurableDistance 对象:
public class Holder {
private MeasurableDistance holder;
public Holder() {};
public add(MeasurableDistance a) {
holder = a;
}
}
或者类似的东西
public class Holder<T extends MeasurableDistance> {
private T holder;
public Holder<T>() {};
public add(T a) {
holder = a;
};
}
对于 1,我认为它们应该非常相似,对吧?明明调用的是非泛型版本
Person a = new Person();
Person b = new Person();
House c = new House();
House d = new House();
computeDistance(a,c);
computeDistance(a,b);
computeDistance(c,d);
将始终有效,因为由于多态性,computeDistance() 会将这些对象视为 MeasurableDistance。通用版本应该也能正常工作吧?编译器会推断出 MeasurableDistance 类型并相应地添加强制转换。即使我想这样调用它:
<Person, House>computeDistance(a,c);
效果是一样的,方法是这样的
Point a = (MeasurableDistance) a.getPosition();
Point b = (MeasurableDistance) b.getPosition();
如果我没记错的话。或者,现在我想想,它应该是这样的:
Point a = (Person) a.getPosition();
Point b = (House) b.getPosition();
它会起作用,因为 Person 和 House 都在实现该方法。
那么泛型方法的优势是什么?我读到它是类型安全的,因为转换总是正确的,但是使用非通用方法你根本不会有转换。
最佳答案
您似乎混淆了使用泛型的原因和使用有界泛型的原因。
使用有界泛型的原因意味着已经有使用泛型的原因。
让我回顾一下。
在 Java tutorials 中解释了使用泛型的原因。 ,最明显的原因之一是:
The following code snippet without generics requires casting:
List list = new ArrayList(); list.add("hello"); String s = (String) list.get(0);
When re-written to use generics, the code does not require casting:
List<String> list = new ArrayList<String>(); list.add("hello"); String s = list.get(0); // no cast
使用有界泛型的原因与使用泛型的原因是分开的。 如果您有使用泛型的理由,使用边界让您要求某种类型的功能:
public class MyClass<T> {
private List<T> list;
...
public void disposeAll() {
for(T e : list)
e.dispose(); // compile time error
}
}
上面的错误可以通过加bound来解决:
public class MyClass<T extends Disposable> {...}
正如您所指出的那样,您展示的案例实际上没有理由使用有界泛型。但这是因为他们一开始就没有(充分的)理由使用泛型。
在情况 2 中,泛型让您可以限制 Holder
可以持有的对象类型:
Holder<House> holder = new Holder<>();
holder.add(new Person()); // compile time error
holder.add(new House());
这不是很有用。没有真正的理由在那里使用泛型。
但如果您还检索值,泛型会很有用:
Holder<House> holder = new Holder<>();
// holder.add(new Person());
holder.add(new House());
House h = holder.get(); // no cast
关于java - 在方法和类中使用泛型和接口(interface)有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37907526/