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生成,仅供参考和借鉴