英文:
Bounded type parameter vs plain base class
问题
在编译时,javac会擦除通用有界类型并用上界替换它。
例如,编译器将把
<T extends Base> void foo(T p) {}
转换为
void foo(Base p) {}
在这种特定情况下,我认为通用类型肯定优于其他选项。但我想了解具体的优势。
英文:
At compile time, javac erases the generic bounded type and replaces it with the upper bound.
For example, the compiler will convert
<T extends Base> void foo(T p) {}
to
void foo(Base p) {}
In this specific case, I think the generics definitely is preferred over the other option. But I would like to know the specific advantages.
答案1
得分: 2
让我通过一个示例来详细解释*有界类型(Bounded Type)*的需求。
假设你正在编写一个将被其他人使用的库或框架。在某个地方(在某个类的方法中),你需要执行一些数值的加法、减法、乘法等操作。那么,你需要什么类型的数据?当然是一个数值类型。于是,你创建了一个名为Number的类。但是,有各种类型的数字,比如浮点数、整数等。所以,你创建了Integer、Float等子类。此外,你还创建了一个名为NumberUtil的类,它为用户提供了一些功能,比如查找平均值、查找数字的频率等。当然,在一个词中:NumberUtil非常棒,每个人都想要使用它。现在,让我们谈谈NumberUtil类中的平均值方法(让我们写一些代码):
class NumberUtil<T extends Number> {
T[] nums;
public NumberUtil(T[] nums) {
this.nums = nums;
}
public Double average() {
Double sum = 0.0;
for(int i=0; i<nums.length; i++) {
sum = sum + nums[i].doubleValue(); // 注意,你确保了T必须是一个数字
// 因此,T必须能够将其值转换为双精度值
}
return sum / nums.length;
}
}
现在,假设其他人正在使用你的库,特别是NumberUtil(因为它太棒了),但他们正在使用自己的类型,称为SomeNumberType。但是有可能,这个SomeNumberType不是Number的子类(或者,如果你将Number声明为一个接口,它没有实现Number接口)。因此,你不能保证SomeNumberType将提供一个*doubleValue()方法。但是,通过编写T extends Number,你确保了在编译时,SomeNumberType必须是Number的子类,一切都将正常运行(至少,它将具有Number类的属性,这意味着它也将有一个doubleValue()*方法)。
英文:
Let me explain the need of a Bounded Type properly through an example.
Let's say you are writing a library or framework that are going to used by other. Let's say in somewhere(in some class method) you need to perform some neumerical addition, subtraction, multiplication etc. So, what type of data do you need for that? Of course a Neumeric type. So, what you've done is created a class Number. But, there are various type of numbers like Floating point, Integer etc. So, you've created Integer, Float subclass etc. Now, you've also created a class NumberUtil which gives some features to user like finding average, finding frequency of numbers etc. And of course, in a single word: NumberUtil is awesome, everyone wants to use it. Now, let's talk about the average method in your NumberUtil class(let's write some code):
class NumberUtil<T extends Number> {
T[] nums;
public NumberUtil(T[] nums) {
this.nums = nums;
}
public Double average() {
Double sum = 0.0;
for(int i=0; i<nums.length; i++) {
sum = sum + nums[i].doubleValue(); // note, you've ensured T must be a number
// so, T must able to convert it's value to double value
}
return sum / nums.length;
}
}
Now, let's assume, some other people are using your library, specifically NumberUtil(cause, it's awesome), but they are using it with their own type called SomeNumberType. But it's possible that, this SomeNumberType doesn't subclass Number (or, it doesn't implement the Number interface, if you've declared Number as an interface). So, you can't guarantee that SomeNumberType will provide a doubleValue() method. But, by writing T extends Number, you've made sure in the compile time that SomeNumberType must be a subclass of Number and everything will work fine(at least, it would have the peropeties of Number class, and that means, it'll also have a doubleValue() method).
答案2
得分: 0
请参考这个链接。
但简而言之,有两点需要注意:
通用方法是引入其自己类型参数的方法。这类似于声明通用类型,但类型参数的范围仅限于声明它的方法。允许静态和非静态的通用方法,以及通用类构造函数。
—https://docs.oracle.com/javase/tutorial/java/generics/methods.html
类型推断是Java编译器根据每个方法调用和相应的声明来确定使调用适用的类型参数(或参数)的能力。推断算法确定参数的类型,如果可用,确定结果被分配或返回的类型。最后,推断算法尝试找到适用于所有参数的最具体类型。
—https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
英文:
Please refer to this link here.
But in short, two things to note:
> Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.
—https://docs.oracle.com/javase/tutorial/java/generics/methods.html
> Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable. The inference algorithm determines the types of the arguments and, if available, the type that the result is being assigned, or returned. Finally, the inference algorithm tries to find the most specific type that works with all of the arguments.
—https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论