java
public class MaximumTest
{
// 比较三个值并返回最大值
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
{
T max = x; // 假设x是初始最大值
if ( y.compareTo( max ) > 0 ){
max = y; //y 更大
}
if ( z.compareTo( max ) > 0 ){
max = z; // 现在 z 更大
}
return max; // 返回最大对象
}
public static void main( String args[] )
{
System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ) );
System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
"apple", "orange", maximum( "pear", "apple", "orange" ) );
}
}
一句话概括这个程序在做什么
这个
程序定义了一个超级通用的"找最大值"方法。这个方法聪明到,无论你给它整数、小数还是字符串,它都能准确地找出最大的那个,而不需要为每种类型都写一遍代码。
第一部分:核心难点 ------ maximum 方法的签名
让我们先盯着这个最复杂的部分看:
java
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
别怕,我们把它像剥洋葱一样一层层剥开。
1. public static
这个简单,说明 maximum 是一个公开的、静态的工具方法。我们可以直接用 MaximumTest.maximum(...) 来调用它,不需要先创建 MaximumTest 的对象。
2. <T extends Comparable<T>>
这是整个程序的"大脑",也是最难理解的部分。我们把它拆成两半:
<T>: 这是在声明一个**"泛型"。你可以把T想象成一个 占位符**,它代表"任何一种类型"。在这次调用中它可能是Integer,下次调用中它可能是String。extends Comparable<T>: 这是对占位符T的一个限制或要求 。它规定:"T不能是随便什么类型,它必须 是一个实现了Comparable接口的类型。"
什么是Comparable接口?
一个类如果实现了Comparable接口,就说明这个类的对象是"可以互相比较大小 的"。它必须提供一个compareTo()方法来告诉别人怎么比。Integer实现了Comparable,所以整数可以比大小。Double实现了Comparable,所以小数可以比大小。String实现了Comparable,所以字符串可以按字典序比大小(比如 "pear" > "apple")。
所以,<T extends Comparable<T>>整句话的意思就是:
"我这个
maximum方法,只接受那些自身可以比较大小 的类型。你传给我一个不能比较的类型,我可不干!"这个限制是编译时的,也就是说,如果你传错了类型,代码根本编译不过去,这就保证了安全。
3. T maximum(T x, T y, T z)
这部分就简单了:
- 返回值类型是
T:你传给我什么类型,我就返回什么类型。 - 参数是
(T x, T y, T z):接受三个T类型的参数。
第二部分:maximum 方法的"身体"
java
T max = x; // 假设x是初始最大值
if ( y.compareTo( max ) > 0 ){
max = y; //y 更大
}
if ( z.compareTo( max ) > 0 ){
max = z; // 现在 z 更大
}
return max; // 返回最大对象
这段代码的逻辑非常清晰,就像我们现实生活中找最大值一样:
T max = x;:先拿出第一个数x,暂时把它当成"擂主"。if ( y.compareTo( max ) > 0 ):让第二个数y上来打擂。y.compareTo(max)的意思是"让y和max比较一下"。- 如果
y比max大,compareTo会返回一个正数(> 0)。 - 如果
y更大,就把y设为新的"擂主"(max = y;)。
- 如果
if ( z.compareTo( max ) > 0 ):让第三个数z上来打擂,和当前的"擂主"max比较。如果z更大,它就成为新擂主。return max;:打擂结束,返回最后的"擂主",也就是三个数中的最大值。
关键点 :正因为我们在方法签名里限制了T必须有compareTo方法,所以在这里我们才能放心大胆地调用y.compareTo(max)和z.compareTo(max)。
第三部分:main 方法里的"魔法"
现在我们来看 main 方法是怎么调用这个"超级方法"的。
调用 1:比较整数
java
System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n", 3, 4, 5, maximum( 3, 4, 5 ) );
- 当编译器看到
maximum(3, 4, 5)时,它发现3, 4, 5都是Integer类型。 - 于是,它就把泛型
T自动推断 为Integer。 - 它检查
Integer是否满足extends Comparable<Integer>的要求?满足! - 于是,方法就变成了
Integer maximum(Integer x, Integer y, Integer z),然后执行找最大值的逻辑,最后返回一个Integer。 %d正好可以打印Integer,完美!
调用 2:比较小数
java
System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n", 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
- 编译器看到
maximum(6.6, 8.8, 7.7),推断出T是Double类型。 - 检查
Double是否满足extends Comparable<Double>?满足! - 方法变成了
Double maximum(Double x, Double y, Double z),执行后返回Double。 %.1f打印Double,完美!
调用 3:比较字符串
java
System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear", "apple", "orange", maximum( "pear", "apple", "orange" ) );
- 编译器看到
maximum("pear", "apple", "orange"),推断出T是String类型。 - 检查
String是否满足extends Comparable<String>?满足! - 方法变成了
String maximum(String x, String y, String z),执行后返回String。 %s打印String,完美!
总结
这个程序的核心思想就是**"代码复用"和"类型安全"**。
- 没有泛型 :你需要写三个不同的方法
maximum(int, int, int),maximum(double, double, double),maximum(String, String, String)。代码重复,很麻烦。 - 有了泛型 :你只需要写一个
maximum方法,它像一个万能工具,可以处理所有"可比较"的类型。同时,因为<T extends Comparable<T>>的限制,它还很安全,不会让你拿不能比较的东西来比较,从而在编译阶段就避免了错误。
希望这个从里到外的详细解释能让你彻底看懂这段代码!如果还有不清楚的地方,随时可以再问。
以上内容由AI生成,仅供参考和借鉴