目录
一、引言
二、编程分析
1、泛型类实现
思路
代码
2、泛型方法实现
思路
代码
三、拓展:数组排序(以冒泡排序为例)
1、int类型 原代码
2、泛型类
3、泛型方法
一、引言
给定一个整型数组,求数组中所有元素的最大值
该题同样是编程入门的基础题。关键在于拓展:能不能通过程序,实现给定的任意类型的数组,都能求出数组中所有元素的最大值?
这里我们先给出整型数组求最大值的代码,作为基础:
public class Util {public int findMaxInt(int[] array) {int max = array[0];for (int i = 0; i < array.length; i++) {if(max < array[i]) {max = array[i];}}return max;}
}
调用并运行:
public class Test {public static void main(String[] args) {int[] array = {1,0,9,4,5};System.out.println("max is " + util.findMaxInt(array));}
}
接下来我们来分析,如果通过泛型类或泛型方法使程序能够适用于任意一个数据类型。
二、编程分析
1、泛型类实现
解题之前,我们首先要了解泛型、泛型上界、泛型方法的概念。对于这些概念有所遗忘的同学,可以阅读文章:🔗Java初识泛型 | 如何通过泛型类/泛型方法获取任意类型的三个数的最大值?的知识解析部分熟悉一下。
这里,我们直接讲解思路,不再进行基础知识的铺垫。
思路
按照泛型的思路,我们试着将原来的类改成泛型类。用占位符E代替原代码中所有的int。但仅仅更改这些,最后会发现编译器在比较的位置报错了:
是什么原因导致编译失败呢?
原因:max和array[i]都是E类型也就是引用类型的变量,两个引用变量之间不能用大于小于号进行大小比较。可行的方法应当是调用比较对象的compareTo()方法。但是,compareTo()方法是不能直接调用的,它要求调用的对象的类型必须实现过Comparable接口。
换句话说,它对类型E有约束,这个约束就是: 必须实现过Comparable接口。因此,这里要用到类型的上界的知识,来进行约束。
public class Util<E extends Comparable<E>> {...
}
<E extends Comparable<E>> 的含义为:传入的E类型必须是实现了Comparable接口的。如果传入的类型没有实现过Comparable接口,那么编译会报错。
此时,我们可以成功地调用compareTo()方法了:
整合后,便能得出完整的代码了。
代码
泛型类:
public class Util<E extends Comparable<E>> {public E findMax(E[] array) {E max = array[0];for (int i = 0; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}
调用:
Integer
public class Test {public static void main(String[] args) {Util<Integer> util = new Util<>();Integer[] array = {1,0,9,4,5};System.out.println("max is " + util.findMax(array));}
}
Double(只需更改main中的数据类型即可,Util类不用变动)
public class Test {public static void main(String[] args) {Util<Double> util = new Util<>();Double[] array = {13.6,100.5,0.0,-3.1,5.8};System.out.println("max is " + util.findMax(array));}
}
String
public class Test {public static void main(String[] args) {Util<String> util = new Util<>();String[] array = {"China","America","Australia","Ireland"};System.out.println("max is " + util.findMax(array));}
}
自定义的类型Tmp,已手动实现了Comparable<Tmp>接口
//Tmp.javapublic class Tmp implements Comparable<Tmp>{public int parameter1;public String parameter2;public Tmp(int parameter1, String parameter2) {this.parameter1 = parameter1;this.parameter2 = parameter2;}@Overridepublic int compareTo(Tmp o) {//以parameter2为标准来比较Tmp//parameter2是String类,比较可以直接调用String类的compareTo方法return this.parameter2.compareTo(o.parameter2);}@Overridepublic String toString() {return "Tmp{" +"parameter1=" + parameter1 +", parameter2='" + parameter2 + '\'' +'}';}
}
//Test.javapublic class Test {public static void main(String[] args) {Util<Tmp> util = new Util<>();Tmp tmp1 = new Tmp(10,"substantial");Tmp tmp2 = new Tmp(20,"circumspect");Tmp tmp3 = new Tmp(5,"coby");Tmp[] array = {tmp1,tmp2,tmp3};System.out.println("max is " + util.findMax(array));}
}
2、泛型方法实现
思路
如果用泛型类实现,则每次使用前还需要创建类对象。能不能把这一个步骤省去呢?答案是可以的,我们可以通过静态泛型方法来完成。
按照泛型方法的语法,我们对原代码稍作修改:
public class Util {public static <E> E findMax(E[] array) {...}
}
此时的Util类已经不再是泛型类了,而是一个普通类。通过在修饰符后添加 static <E> 将普通方法改为了静态泛型方法。但此时还不够完善,同样的,我们需要把类型参数E实现了Comparable接口这一约束体现出来。只需要把<E>改为 <E extends Comparable<E>> 即可。
代码
public class Util {public static <E extends Comparable<E>> E findMax(E[] array) {E max = array[0];for (int i = 0; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}
此时,测试时的代码也更加简略了:
public class Test {public static void main(String[] args) {Tmp tmp1 = new Tmp(10,"substantial");Tmp tmp2 = new Tmp(20,"circumspect");Tmp tmp3 = new Tmp(5,"coby");Tmp[] array = {tmp1,tmp2,tmp3};System.out.println("max is " + Util.findMax(array));}
}
三、拓展:数组排序(以冒泡排序为例)
1、int类型 原代码
//Tmp.javapublic class Tmp{public static void bubbleSort(int[] array){for (int i = 0; i < array.length-1; i++) {boolean flag = false;for (int j = 0; j < array.length-1-i; j++) {if(array[j] > array[j+1]) {int tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;flag = true;}}if(!flag) {break;}}}
}
//Test.javaimport java.util.Arrays;public class Test {public static void main(String[] args) {int[] array = {0,3,1,8,9,6,4,5,2};Tmp.bubbleSort(array);System.out.println(Arrays.toString(array));}
}
2、泛型类
//Util.javapublic class Util<E extends Comparable<E>> {public void bubbleSort(E[] array){for (int i = 0; i < array.length-1; i++) {boolean flag = false;for (int j = 0; j < array.length-1-i; j++) {if(array[j].compareTo(array[j+1]) > 0) {E tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;flag = true;}}if(!flag) {break;}}}
}
//Test.javaimport java.util.Arrays;public class Test {public static void main(String[] args) {Util<Integer> util = new Util<>();Integer[] array = {10,8,-33,7,21,78};util.bubbleSort(array);System.out.println(Arrays.toString(array));}
}
3、泛型方法
//Util.javapublic class Util {public static <E extends Comparable<E>> void bubbleSort(E[] array){for (int i = 0; i < array.length-1; i++) {boolean flag = false;for (int j = 0; j < array.length-1-i; j++) {if(array[j].compareTo(array[j+1]) > 0) {E tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;flag = true;}}if(!flag) {break;}}}
}
//Test.javaimport java.util.Arrays;public class Test {public static void main(String[] args) {Integer[] array = {10,8,-33,7,21,78};Util.bubbleSort(array);System.out.println(Arrays.toString(array));}
}
拓展阅读: 🔗Java初识泛型 | 如何通过泛型类/泛型方法获取任意类型的三个数的最大值?