Version: Next

泛型

定义含有泛型的类

未知的数据类型,不确定使用什么类型时可以使用泛型,可以接收任意的数据类型

public class Demo01GenericClass<E> {
private E name;
public void setName(E name) {
this.name = name;
}
public E getName() {
return name;
}
@Test
public void testGenericClass(){
Demo01GenericClass c1 = new Demo01GenericClass();
c1.setName(123);
System.out.println(c1.getName());
Demo01GenericClass<Double> c2 = new Demo01GenericClass<>();
c2.setName(11.1);
System.out.println(c2.getName());
}
}
123
11.1

定义含有泛型的方法

定义含有泛型的方法:

  • 泛型定义在方法的修饰符和返回值之间
  • 在调用时确定泛型的数据类型,传递什么就是什么类型
public class Demo02GenericMethod {
/***
* 定义一个含有泛型的方法
* @param anyType 泛型形参
* @param <AnyType> 自定义泛型
*/
public <AnyType> void genericMethod(AnyType anyType){
System.out.println(anyType);
}
/***
* 定义一个含有泛型的静态方法
*/
public static <AnyType> void genericStaticMethod(AnyType anyType){
System.out.println(anyType);
}
}
/***
* 测试含有泛型的方法
*/
@Test
public void testGenericMethod(){
//创建一个GenericMethod对象
Demo02GenericMethod instance = new Demo02GenericMethod();
instance.genericMethod("123");
instance.genericMethod(321);
instance.genericMethod('C');
}
123
321
C
/***
* 测含有泛型的静态方法
*/
@Test
public void testGenericStaticMethod(){
Demo02GenericMethod.genericStaticMethod(123);
Demo02GenericMethod.genericStaticMethod('A');
Demo02GenericMethod.genericStaticMethod(1.3);
Demo02GenericMethod.genericStaticMethod("哈哈哈");
}
123
A
1.3
哈哈哈

定义含有泛型的接口

public interface Demo03GenericInterface<AnyType> {
public abstract void method(AnyType anyType);
}
public class GernericInterfaceImpl implements Demo03GenericInterface<String> {
@Override
public void method(String s) {
System.out.println(s);
}
@Test
public void test(){
GernericInterfaceImpl2<Integer> g1 = new GernericInterfaceImpl2<>();
g1.method(123);
GernericInterfaceImpl g2 = new GernericInterfaceImpl();
g2.method("123");
}
}
123
/***
* 第二种方式: 接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
* 相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
*/
class GernericInterfaceImpl2<E> implements Demo03GenericInterface<E> {
@Override
public void method(E e) {
}
}

泛型通配符

泛型通配符

  • 不知道使用什么类型来接收的时候,此时可以使用?,表示未知通配符

  • 此时只能接收数据,作为参数;不能往该集合中存储数据

使用方式:不能创建对象使用,只能作为方法的参数使用

  • 一个可以遍历所有类型ArrayList的方法,这时候我们不知道ArrayList使用什么数据类型,用?来接收数据类型,泛型没有继承概念,不能写<Object>

  • 定义的时候不能用, 参数上才能用

public static void printArray(ArrayList<?> list){
for(Object o : list){
System.out.println(o);
}
}
  • 测试:用同一个方法遍历Integer的ArrayList和String的ArrayList
@Test
public void testWenHao(){
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
printArray(list01);
printArray(list02);
}
1
2
a
b

在定义集合是指定泛型

/***
* 创建集合对象不适用泛型
* 好处:里面啥都能放,默认类型是Object
* 弊端:集合不安全,会引发异常
*/
@Test
public void testWithoutGeneric() {
ArrayList list = new ArrayList();
//参数类型此时是Object
list.add("abc");
list.add(123);
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
//想要使用String类特有的方法,length获取字符串的长度;不能使用 多态Object obj = "abc";
//不能使用子类特有方法,向下转型
// Integer -> String 类型转换异常
String str = (String) iterator.next();
}
}
/***
* 使用泛型定义集合对象
* 好处:
* 1.避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
* 2.把运行期异常提升到了编译期
*/
@Test
public void testGeneric() {
ArrayList<String> list = new ArrayList<>();
//此时参数类型为String
list.add("abc");
list.add(123 + "");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
System.out.println(str.length());
}
}

泛型练习题

ArrayCompare

写一个泛型方法 ArrayListCompare, 传入两个 ArrayList, 里面的元素是任意类型,遍历比较两个 ArrayList 里面的元素是否相等, 如果都相等返回 true , 不相等返回 false

public class ArrayCompare {
public static void log(String format, Object... args) {
System.out.println(String.format(format, args));
}
public static void ensure(boolean condition, String message) {
if (!condition) {
log("%s", message);
} else {
log("测试成功");
}
}
//写一个泛型方法 ArrayListCompare, 传入两个 ArrayList, 里面的元素是任意类型,
//遍历比较两个 ArrayList 里面的元素是否相等, 如果都相等返回 true , 不相等返回 false
public static <T> Boolean ArrayCompare(ArrayList<T> l1, ArrayList<T> l2) {
if (l1.size() != l2.size()) {
return false;
}
for (int i = 0; i < l1.size(); i++) {
if (l1.get(i) != l2.get(i)) {
return false;
}
}
return true;
}
public static void testArrayCompare() {
ArrayList<String> a1 = new ArrayList<>(Arrays.asList("InterfaceA", "B", "C", "D"));
ArrayList<String> expect1 = new ArrayList<>(Arrays.asList("InterfaceA", "B", "C", "D"));
ensure(ArrayCompare(a1, expect1), "test ArrayCompare 1");
ArrayList<Integer> a2 = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
ArrayList<Integer> expect2 = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
ensure(!ArrayCompare(a2, expect2), "test ArrayCompare 2");
}
public static void main(String[] args) {
testArrayCompare();
}
}

ArrayListMake

写一个函数 ArrayListMake, 传入一个任意类型的数组, 返回一个 ArrayList

public class ArrayListMake {
public static void log(String format, Object... args) {
System.out.println(String.format(format, args));
}
public static void ensure(boolean condition, String message) {
if (!condition) {
log("%s", message);
} else {
log("测试成功");
}
}
//写一个函数 ArrayListMake, 传入一个任意类型的数组, 返回一个 ArrayList
public static <T> ArrayList<T> ArrayListMake(T[] arrays) {
ArrayList<T> list = new ArrayList<>();
for (int i = 0; i < arrays.length; i++) {
list.add(arrays[i]);
}
return list;
}
class User {
public String name;
public String content;
public User(String name, String content) {
this.name = name;
this.content = content;
}
}
public void testArrayListMake() {
User u1 = new User("test1", "content1");
User u2 = new User("test2", "content2");
User[] userArray = {u1, u2};
ArrayList<User> userList = ArrayListMake(userArray);
for (int i = 0; i < userList.size(); i++) {
User e1 = userArray[i];
User e2 = userList.get(i);
ensure(e1.name.equals(e2.name), "testArrayListMake");
ensure(e1.content.equals(e2.content), "testArrayListMake");
}
}
public static void main(String[] args) {
new ArrayListMake().testArrayListMake();
}
}

ArrayReverse

写一个函数 ArrayListReverse, 可以传入任意类型的 ArrayList,把 ArrayList 里面的元素倒序排列

public class ArrayReverse {
public static void log(String format, Object... args) {
System.out.println(String.format(format, args));
}
public static void ensure(boolean condition, String message) {
if (!condition) {
log("%s", message);
} else {
log("测试成功");
}
}
//写一个函数 ArrayListReverse, 可以传入任意类型的 ArrayList
//把 ArrayList 里面的元素倒序排列
public static <T> ArrayList<T> ArrayReverse(ArrayList<T> list) {
ArrayList<T> resultList = new ArrayList<>();
for (int i = list.size()-1; i >= 0 ; i--) {
resultList.add(list.get(i));
}
return resultList;
}
public static void testArrayReverse() {
ArrayList<String> arrayList1 = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<Integer> arrayList2 = new ArrayList<>(Arrays.asList(1, 2, 3));
ArrayList<String> resultArrayList1 = ArrayReverse(arrayList1);
ArrayList<Integer> resultArrayList2 = ArrayReverse(arrayList2);
ArrayList<String> ExpresultList1 = new ArrayList<>(Arrays.asList("C", "B", "A"));
ArrayList<Integer> ExpresultList2 = new ArrayList<>(Arrays.asList(3, 2, 1));
ensure(ArrayCompare.ArrayCompare(resultArrayList1,ExpresultList1),"错了");
ensure(ArrayCompare.ArrayCompare(resultArrayList2,ExpresultList2),"错了");
}
public static void main(String[] args) {
testArrayReverse();
}
}

ElementMirror

public class ElementMirror {
public static void log(String format, Object... args) {
System.out.println(String.format(format, args));
}
public static void ensure(boolean condition, String message) {
if (!condition) {
log("%s", message);
} else {
log("测试成功");
}
}
//写一个函数 ElementMirror, 可以传入任意元素, 然后返回这个元素
public static <T> T ElementMirror(T e) {
return e;
}
public static void testElementMirror() {
String a1 = "hello";
String r1 = ElementMirror(a1);
ensure(r1.equals(a1), "testElementMirror 1");
Integer a2 = 123;
Integer r2 = ElementMirror(a2);
ensure(r2.equals(a2), "testElementMirror 2");
}
public static void main(String[] args) {
testElementMirror();
}
}

实现一个ArrayList

public class MyArrayList<T> {
T[] data;
@Override
public String toString() {
return "MyArrayList{" +
"data=" + Arrays.toString(data) +
'}';
}
public static void log(String format, Object... args) {
System.out.println(String.format(format, args));
}
public static void ensure(boolean condition, String message) {
if (!condition) {
log("%s", message);
} else {
log("测试成功");
}
}
//写一个泛型类 MyArrayList 的构造器, 初始化的时候传入一个任意类型的数组
//这个数组保存在类里面一个叫做 data 的属性里
public MyArrayList(T[] data) {
this.data = data;
}
//给泛型类 MyArrayList 加上一个 get 方法, 传入一个索引值, 得到数组里的一个元素
public T get(int index) {
return data[index];
}
//给泛型类 MyArrayList 加上一个 add 方法,
// 传入一个元素, MyArrayList.data 数组的尾部添加进这个新的元素
//Arrays.copyOf 函数可以给数组扩容, 返回一个包含原数组元素的更长的数组
public void add(T e) {
T[] resultData = Arrays.copyOf(this.data, this.data.length + 1);
resultData[resultData.length - 1] = e;
this.data = resultData;
}
//给泛型类 MyArrayList 加上一个 extend 方法, 传入一个数组,
// 把这个数组加到 MyArrayList.data 数组的尾部
public void extend(T[] array) {
for (int i = 0; i < array.length; i++) {
add(array[i]);
}
}
public static void testMyArrayList() {
String[] data1 = {"hello", "world"};
MyArrayList<String> a1 = new MyArrayList<>(data1);
ensure(Arrays.deepEquals(a1.data, data1), "testMyArrayList 1 ");
Integer[] data2 = {1, 2, 3, 4};
MyArrayList<Integer> a2 = new MyArrayList<>(data2);
ensure(Arrays.deepEquals(a2.data, data2), "testMyArrayList 1 ");
}
public static void testGet() {
String[] data = {"hello", "world", "Java"};
MyArrayList<String> a = new MyArrayList<>(data);
ensure(a.get(0).equals("hello"), "test add 1");
ensure(a.get(1).equals("world"), "test add 2");
ensure(a.get(2).equals("Java"), "test add 3");
}
public static void testAdd() {
String[] data = {};
MyArrayList<String> a = new MyArrayList<>(data);
a.add("hello");
a.add("world");
a.add("Java");
ensure(a.get(0).equals("hello"), "test add 1");
ensure(a.get(1).equals("world"), "test add 2");
ensure(a.get(2).equals("Java"), "test add 3");
}
public static void testExtend() {
String[] data = {"A", "B"};
MyArrayList<String> a = new MyArrayList<>(data);
String[] extend1 = {"C"};
String[] extend2 = {"D", "E", "F"};
a.extend(extend1);
a.extend(extend2);
ensure(a.get(2).equals("C"), "test add 1");
ensure(a.get(3).equals("D"), "test add 2");
ensure(a.get(4).equals("E"), "test add 3");
}
public static void main(String[] args) {
testExtend();
}
}