Java 泛型与集合的深入解析:原理、应用与实践

泛型的基本原理

为什么需要泛型

在Java 5之前,Java的集合类只能存储Object类型的对象。这意味着,存储在集合中的对象在取出时需要进行类型转换,这不仅繁琐,而且容易出错。泛型通过在编译时进行类型检查,确保类型安全,减少了运行时错误。

泛型的定义

泛型通过类型参数来实现,这些类型参数在使用时被具体的类型替换。常见的类型参数命名如下:

  • T:Type(类型)
  • E:Element(元素)
  • K:Key(键)
  • V:Value(值)

泛型类

泛型类是在类定义中使用类型参数。例如:

class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

在使用泛型类时,需要指定具体的类型:

public class GenericClassExample {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setContent("Hello, World!");
        System.out.println(stringBox.getContent()); // 输出: Hello, World!

        Box<Integer> integerBox = new Box<>();
        integerBox.setContent(123);
        System.out.println(integerBox.getContent()); // 输出: 123
    }
}

泛型方法

泛型方法是在方法定义中使用类型参数。类型参数在方法名之前用尖括号<>指定。例如:

public class GenericMethodExample {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] stringArray = {"A", "B", "C", "D", "E"};

        printArray(intArray); // 输出: 1 2 3 4 5 
        printArray(stringArray); // 输出: A B C D E 
    }
}

泛型和集合

Java集合框架是处理一组对象的标准方法。常见的集合包括ListSetMap。结合泛型使用集合,可以提高类型安全性和代码的可读性。

使用泛型集合
import java.util.ArrayList;
import java.util.List;

public class GenericCollectionExample {
    public static void main(String[] args) {
        // 创建一个用于存储字符串的泛型列表
        List<String> stringList = new ArrayList<>();
        
        // 向列表中添加字符串
        stringList.add("Hello");
        stringList.add("World");

        // 使用增强型 for 循环遍历并打印列表中的每个字符串
        for (String str : stringList) {
            System.out.println(str);
        }
    }
}
//程序运行后,输出结果为:
//Hello
//World

在这个例子中,List<String>确保了stringList只能包含String类型的元素。

通配符

通配符用于在泛型中表示未知类型,有三种主要形式:

  1. 无界通配符<?>,表示任何类型。
  2. 有界通配符(上界)<? extends T>,表示类型T及其子类型。
  3. 有界通配符(下界)<? super T>,表示类型T及其父类型。
无界通配符

无界通配符<?>表示任何类型。例如:

import java.util.ArrayList;
import java.util.List;

public class WildcardExample {
    public static void printList(List<?> list) {
        for (Object elem : list) {
            System.out.print(elem + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);
        intList.add(3);

        List<String> stringList = new ArrayList<>();
        stringList.add("A");
        stringList.add("B");
        stringList.add("C");

        printList(intList); // 输出: 1 2 3 
        printList(stringList); // 输出: A B C 
    }
}
有界通配符(上界)

有界通配符<? extends T>表示类型T及其子类型。例如:

import java.util.ArrayList;
import java.util.List;

public class BoundedWildcardExample {
    public static double sumOfList(List<? extends Number> list) {
        double sum = 0.0;
        for (Number number : list) {
            sum += number.doubleValue();
        }
        return sum;
    }

    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);
        intList.add(3);

        List<Double> doubleList = new ArrayList<>();
        doubleList.add(1.1);
        doubleList.add(2.2);
        doubleList.add(3.3);

        System.out.println("Sum of intList: " + sumOfList(intList)); // 输出: Sum of intList: 6.0
        System.out.println("Sum of doubleList: " + sumOfList(doubleList)); // 输出: Sum of doubleList: 6.6
    }
}
有界通配符(下界)

有界通配符<? super T>表示类型T及其父类型。例如:

import java.util.ArrayList;
import java.util.List;

public class LowerBoundedWildcardExample {
    public static void addNumbers(List<? super Integer> list) {
        list.add(1);
        list.add(2);
        list.add(3);
    }

    public static void main(String[] args) {
        List<Number> numberList = new ArrayList<>();
        addNumbers(numberList);

        for (Number number : numberList) {
            System.out.println(number);
        }
    }
}

泛型和继承

泛型不支持多态,例如,List<Number>不能被赋值为List<Integer>。但是可以通过使用通配符来实现类似的效果。

示例:泛型和继承
import java.util.ArrayList;
import java.util.List;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Employee extends Person {
    public Employee(String name) {
        super(name);
    }
}

public class GenericInheritanceExample {
    public static void printNames(List<? extends Person> people) {
        for (Person person : people) {
            System.out.println(person.getName());
        }
    }

    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Alice"));
        employees.add(new Employee("Bob"));

        printNames(employees); // 输出: Alice Bob
    }
}

总结

通过以上更详细的解释和示例,我们可以更深入地理解泛型和集合的使用:

  1. 泛型类:定义包含类型参数的类,使用时指定具体类型。
  2. 泛型方法:定义包含类型参数的方法,使用时指定具体类型。
  3. 集合和泛型:使用泛型集合可以保证类型安全。
  4. 通配符:表示未知类型,提供更灵活的类型控制。
  5. 泛型和继承:使用通配符实现泛型的多态性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值