Collection接口、泛型、包装类

一 、Collection接口

1 、基本关系说明

Java 集合框架Java Collection Framework ,又被称为容器container ,是定义在 java.util 包下的一组接口interfaces 和其实现类classes 。
其主要表现为将多个元素element 置于一个单元中,用于对这些元素进行快速、便捷的存储store 、检索retrieve 、管理manipulate ,即平时我们俗称的增删查改CRUD 。
在这里插入图片描述
Collection :用来存储管理一组对象objects ,这些对象一般被成为元素elements

  1. Set : 元素不能重复,背后隐含着查找/搜索的语义
  2. SortedSet : 一组有序的不能重复的元素
  3. List : 线性结构
  4. Queue : 队列
  5. Deque : 双端队列

2、 Collection 常用方法说明

在这里插入图片描述

3、 代码示例

下面示例代码涉及到ArrayList将在后面博客详细介绍,此处仅仅是作为例子使用。

import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;
public class Demo {
public static void main(String[] args) {

	Collection<String> list = new ArrayList<>();
	System.out.println(list.size());//获取元素个数
	System.out.println(list.isEmpty());//判断是否为空
	//添加元素
	list.add("我");
	list.add("爱");
	list.add("Java");
	System.out.println(list.size());
	System.out.println(list.isEmpty());
	
	//将list转为对象数组
	Object[] array = list.toArray();
	//打印数组内容
	System.out.println(Arrays.toString(array));
	for (String s : list) {
		System.out.println(s);
	}
	//删除元素
	list.remove("爱");
	for (String s : list) {
		System.out.println(s);
	}
	//清空
	list.clear();
	System.out.println(list.size());
	System.out.println(list.isEmpty());
}

二 、泛型(Generic)

1 、泛型的诞生

我们之前实现过的顺序表,只能保存 int 类型的元素,如果现在需要保存 指向 Person 类型对象的引用的顺序表,请问应该如何解决?如果又需要保存指向 Book 对象类型的引用呢?
答:将我们的顺序表的元素类型定义成 Object 类型,这样我们的 Object 类型的引用可以指向 Person 类型的对象或者指向 Book 类型的对象了。
代码示例:

public class MyArrayList {
	private Object[] array; // 保存顺序表的元素,即 Object 类型的引用
	private int size; // 保存顺序表内数据个数
	public void add(Object o) { 尾插 }
	public Object get(int index) { 获取 index 位置的元素 }
}

//使用
MyArrayList books = new MyArrayList();
for (int i = 0; i < 10; i++) {
books.add(new Book()); // 尾插 10 本书到顺序表
}

如上述代码所示,链表中就可以添加任意类型的成员了。
但是如果直接父类引用改为具体的类型还可以吗?看下面代码:

MyArrayList books = new MyArrayList();
books.add(new Book);
// 将 Object 类型转换为 Person 类型,需要类型转换才能成功
// 这里编译正确,但运行时会抛出异常 ClassCastException
Person person = (Person)books.get(0);

此时将Object 类型转换为 Person 类型在编译时期正确,但是在运行时会抛出ClassCastException异常。
所以我们需要这样一种机制:

  • 增加编译期间的类型检查
  • 取消类型转换的使用

因此, 泛型就此诞生!

2 、泛型的分类以及使用

1) 、泛型分类

泛型主要有两大分类:

  • 1.泛型类
  • 2.泛型方法
2) 、泛型类的使用
  • 1.尖括号 <> 是泛型的标志
  • 2.E 是类型变量(Type Variable),变量名一般要大写
  • 3.E 在定义时是形参,代表的意思是 MyArrayList 最终传入的类型,但现在还不知道

代码:

public class MyArrayList<E> {
	private E[] array;
	private int size;
}

注意: 泛型类可以一次有多个类型变量,用逗号分割。

// 定义了一个元素是 Book 引用的 MyArrayList
MyArrayList<Book> books = new MyArrayList<Book>();
books.add(new Book());
// 会产生编译错误,Person 类型无法转换为 Book 类型
books.add(new Person());
// 不需要做类型转换
Book book = book.get(0);
// 不需要做类型转换
// 会产生编译错误,Book 类型无法转换为 Person 类型
Person person = book.get(0);

通过以上代码,我们可以看到泛型类的一个使用方式:只需要在所有类型后边跟尖括号,并且尖括号内是真正的类型,即 E 可以看作的最后的类型。
注意: Book 只能想象成 E 的类型,但实际上 E 的类型还是 Object。

3) 、泛型方法的使用

泛型方法的使用:方法中的参数可以接收任意类型的参数

public class  Tool {  

    public <E> hello(E t){
        System.out.println(t);
    }
}

public class Main {

    public static void main(String[] args) {
        Tool  tol= new Tool ();
        tol.hello("wy");
    }
}

3 、泛型总结

1. 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
2. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
3. 泛型是一种编译期间的机制,即运行期间没有泛型的概念。也就是说MyArrayList< Person>和 MyArrayList< Book> 在运行期间是一个类型。
4. 泛型是 java 中的一种合法语法,标志就是尖括号 <>

三 、包装类(Wrapper Class)

1 、为什么会有包装类型呢?

问题一: 泛型利用Object 引用可以指向任意类型的对象,但有8 种基本数据类型不是对象,那岂不是刚才的泛型机制要失效了?
答: 实际上也确实如此,为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程中,会将类似 int 这样的值包装到一个对象中去。

问题二: 如果我们在项目中自定义类的数据成员为简单类型,当没有初始化,它默认是对应的零值(比如int就是0),这样就会对数据造成误解,到底是该数据为0还是默认是0呢?
答: 基本数据类型的确会对数值咋成误解,但是Integer这样的包装类型没有初始话就是null,并不会对数值造成误解。

2 、基本数据类型和包装类直接的对应关系

在这里插入图片描述
基本就是类型的首字母大写,除了 Integer 和 Character。

3 、包装类的使用

1)装箱(boxing)和拆箱(unboxing)
  • 装箱操作:将基本数据类型转为包装数据类型
  • 拆箱操作:将包装数据类型转为基本数据类型

代码示例:

int i = 10;
// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中
Integer ii = Integer.valueOf(i);
Integer ij = new Integer(i);
// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中
int j = ii.intValue();
1)自动装箱(autoboxing)和自动拆箱(autounboxing)

可以看到在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。

int i = 10;

Integer ii = i; // 自动装箱
Integer ij = (Integer)i; // 自动装箱

int j = ii; // 自动拆箱
int k = (int)ii; // 自动拆箱

注意: 自动装箱和自动拆箱是工作在编译期间的一种机制。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值