Java泛型与集合:提升类型安全与代码复用性
发布时间: 2025-08-17 02:25:01 阅读量: 2 订阅数: 6 

# Java泛型与集合:提升类型安全与代码复用性
## 1. 泛型与集合概述
Java 5.0引入泛型的主要原因之一是提高Java集合框架(JCF)类的可用性和可靠性。在Java 5.0之前,集合类(如`ArrayList`)可以存储不同类型的对象,这可能导致类型安全问题。以下是一个示例,展示了在Java 5.0之前如何使用`ArrayList`存储`Book`对象:
```java
import java.util.*;
class Book {
private String author;
public Book(String name) {
setAuthor(name);
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
public class Main {
public static void main(String[] args) {
List bookList = new ArrayList();
bookList.add(new Book("Jane Austin"));
bookList.add(new Book("Charles Dickens"));
bookList.add(new Book("Henry James"));
Iterator itr = bookList.iterator();
while (itr.hasNext()) {
Book book = (Book) itr.next();
System.out.println(book.getAuthor());
}
}
}
```
在上述代码中,需要将从迭代器中获取的对象强制转换为`Book`类型。这是因为`ArrayList`可以存储任何类型的对象,即使我们知道`bookList`只包含`Book`对象。
### 1.1 泛型集合的优势
Java 5.0引入泛型后,集合类可以指定存储对象的类型,从而提高类型安全性。以下是使用泛型`ArrayList`存储`Book`对象的示例:
```java
import java.util.*;
class Book {
private String author;
public Book(String name) {
setAuthor(name);
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Book> booklist = new ArrayList<Book>();
booklist.add(new Book("Jane Austin"));
booklist.add(new Book("Charles Dickens"));
booklist.add(new Book("Henry James"));
Iterator<Book> itr = booklist.iterator();
while (itr.hasNext()) {
Book book = itr.next();
System.out.println(book.getAuthor());
}
}
}
```
在这个示例中,`ArrayList`被声明为只存储`Book`对象,因此在使用迭代器访问元素时,不需要进行类型转换。
### 1.2 for - each循环
使用for - each循环可以更简洁地访问集合中的元素:
```java
for (Book book : booklist) {
System.out.println(book.getAuthor());
}
```
### 1.3 嵌套泛型类声明
可以创建嵌套的泛型类,例如创建一个存储`Locker<Book>`对象的`ArrayList`:
```java
import java.util.*;
class Book {
private String author;
public Book(String name) {
setAuthor(name);
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
class Locker<T> {
private T content;
public Locker() {
store(null);
}
public T retrieve() {
return content;
}
public void store(T item) {
content = item;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Locker<Book>> bookLockerList = new ArrayList<Locker<Book>>();
Locker<Book> bookLocker = new Locker<Book>();
bookLocker.store(new Book("Jane"));
bookLockerList.add(bookLocker);
for (Locker<Book> locker : bookLockerList) {
System.out.println(locker.retrieve().getAuthor());
}
}
}
```
## 2. 定义简单的泛型链表
在之前的实现中,不同的节点类(如`Node`和`BNode`)的区别仅在于节点中存储的数据类型。使用泛型可以消除为每种类型的项创建自定义节点类的需要。以下是一个泛型`Node`类的定义:
```java
class Node<E> {
private E item;
private Node next;
public Node() {
this(null, null);
}
public Node(E data, Node node) {
setItem(data);
setNext(node);
}
public E getItem() {
return item;
}
public Node<E> getNext() {
return next;
}
public void setItem(E data) {
item = data;
}
public void setNext(Node<E> node) {
next = node;
}
}
```
以下是创建一个包含三个节点的链表的示例,每个节点存储一个`String`对象:
```java
Node<String> one, two, three;
three = new Node<String>("trois", null);
two = new Node<String>("deux", three);
one = new Node<String>("un", two);
```
在这个链表中,每个节点的链接字段只能指向相同实际类型的节点,从而保证链表是同质的。
### 2.1 定义泛型链表类
为了让客户端程序员更方便地使用同质链表,可以定义一个泛型链表类`SimpleLinkedList`:
```java
import java.util.NoSuchElementException;
class SimpleLinkedList<E> {
private Node head;
private Node tail;
public SimpleLinkedList() {
setEmpty();
}
public void add(E item) {
Node node = new Node(item, null);
if (isEmpty()) {
head = tail = node;
} else {
tail.setNext(node);
tail = node;
}
}
public E get(int index) throws NoSuchElementException {
if (index < 0) {
throw new NoSuchElementException();
}
int loc = 0;
Node p = head;
while (loc < index) {
p = p.getNext();
if (p == null) {
throw new NoSuchElementException();
}
loc++;
}
return p.getItem();
}
public boolean isEmpty() {
if (head == null && tail == null) {
return true;
} else {
return false;
}
}
public void setEmpty() {
head = tail = null;
}
class Node {
private E item;
private Node next;
public Node() {
this(null, null);
}
public Node(E data, Node node) {
setItem(data);
setNext(node);
}
public E getItem() {
return item;
}
public Node getNext() {
return next;
}
public void setItem(E data) {
item = data;
}
public void setNext(Node node) {
next = node;
}
}
}
```
以下是使用`SimpleLinkedList`类的示例:
```java
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random generator = new Random();
SimpleLinkedList<Integer> list = new SimpleLinkedList<Integer>();
for (int i = 0; i < 1000; i++) {
list.add(new Integer(generator.nextInt()));
}
int negCnt = 0;
for (int i = 0; i < 1000; i++) {
Integer num = list.get(i);
if (num.intValue() < 0) {
negCnt++;
}
}
System.out.println("Number of negative integers = " + negCnt);
}
}
```
### 2.2 链表遍历的问题
通过不断增加索引值调用`get`方法来遍历链表效率较低,因为每次调用`get`方法都会从头节点开始搜索。因此,`java.util`中的完整集合类支持使用迭代器来高效地遍历列表中的项。
## 3. 泛型、继承和Java接口
### 3.1 泛型超类的子类
当定义泛型超类的子类时,必须在子类中包含超类的类型参数。例如,定义`Locker`类的子类`LockerSub`:
```java
class Locker<T> {
private T content;
public Locker() {
store(null);
}
public T retrieve() {
return content;
}
public void store(T item) {
content = item;
}
}
public class LockerSub<T> extends Locker<T> {
private int id;
private static int idCounter = 100;
public LockerSub() {
this(null);
}
public LockerSub(T item) {
s
```
0
0
相关推荐










