学习编程语言的人都知道数组是具有相同数据类型的一组数据集合,java中将数组看做一个对象,虽然基本的数据类型不是对象,但是由基本的数据类型组成的数组则是对象,所以在程序设计中引入数组可以有效的管理和处理数据,数组则有静态数组和动态数组之分;静态数组有时候存在自身的不足,比如一个会场现有30个人,所以摆了30把椅子,但是后续有人再来,这三十把椅子肯定不够,再比如,实际来了30个人,你摆了300把椅子,这不就构成资源浪费吗?在实际生活中根据参加会议人数情况可以适当增加或减少椅子,同样在java中也可以引入动态数组解决编程问题;下面看一个动态数组的例子
/**
* 动态数组,用来装字符串的动态数组
*
* @author 王伟
*
*/
public class ArrayQueue {
//定义一个用来存放数据的数组
//初始长度为0,表示没有装任何数据
String[] src = new String[0];
/**
* 将指定的元素加入容器
*
* @param s
* 要加入到容器中的元素
*/
public void add(String s) {
//定义一个新数组,用来装数据,长度比src+1
String[] dest = new String[src.length+1];
//将新加进的元素放入新数组的最后一个下标位置
dest[dest.length-1]=s;
//将原来数组中的数据按照下标顺序拷贝到新数组
for(int i=0;i<src.length;i++){
dest[i] = src[i];
}
//将src指向新数组
src = dest;
}
/**
* 获取指定下标位置的元素
*
* @param index
* 要获取的元素的下标
* @return 返回获取到的元素
*/
public String get(int index) {
return src[index];
}
/**
* 修改指定位置元素的值
*
* @param index要修改的元素位置
* @param s
* 修改后的新元素
*/
public void update(int index, String s) {
}
/**
* 将指定元素插入到指定位置
* @param index 要插入元素的位置
* @param s 要插入的新元素
*/
public void insert(int index, String s) {
}
/**
* 删除指定位置的元素
*
* @param index
* 要删除的元素的下标
*/
public void delete(int index) {
}
/**
* 获得容器中元素个数的方法
*
* @return 返回元素的个数
*/
public int size() {
return src.length;
}
}
通过以上例子可以看出动态数组的好处在于其长度可以改变,适当的解决了静态数组遗留的一些问题,java中Object是最上层的父类,在程序设计时通常传入的值与返回的值都以Object类型为主;如果在类名后添加一个<E >语句,则使用了泛型机制,是动态数组可以装任意类型的数据;比如一块地我们为它分配10颗桃树作为实验,以后逐年增加10颗,下面看一个使用泛型动态数组的例子
/**
* 动态数组,用来装任意类型的动态数组
*
* @author 王伟
*
*/
public class ArrayQueue<E> {
private int len = 0;// 长度
private int Capacity;// 初始容量
private int rate;// 增长比率
// 定义一个用来存放数据的数组
// 初始长度为0,表示没有装任何数据
Object[] src;
public ArrayQueue() {
this.initContiner = 10;
this.rate = 10;
src = new Object[initContiner];
}
// 创建容器对象的时候指定容量和增长比率
public ArrayQueue(int initContiner, int rate) {
this.initContiner = initContiner;
this.rate = rate;
src = new Object[initContiner];
}
/**
* 将指定的元素加入容器
*
* @param s
* 要加入到容器中的元素
*/
public void add(E s) {
// 如果长度小于容量,就将元素放到数组第一个为null的位置
if (len >= src.length) {
// 创建新数组
// 定义一个新数组,用来装数据,长度比src+1
Object[] dest = new Object[src.length + rate];
// 将源数组中的数据按照下标顺序拷贝到新数组
System.arraycopy(src, 0, dest, 0, len);
src = dest;
}
src[len] = s;
len++;
}
/**
* 获取指定下标位置的元素
*
* @param index
* 要获取的元素的下标
* @return 返回获取到的元素
*/
public E get(int index) {
return (E) src[index];
}
/**
* 修改指定位置元素的值
*
* @param index要修改的元素位置
* @param s
* 修改后的新元素
*/
public void update(int index, E s) {
if (index >= 0 && index < size()) {
src[index] = s;
} else {
System.out.println("指定的下标超出范围!!!");
}
}
/**
* 将指定元素插入到指定位置
*
* @param index
* 要插入元素的位置
* @param s
* 要插入的新元素
*/
public void insert(int index, E s) {
if (index >= 0 && index < size()) {
// 定义新数组,长度比原数组+1
Object[] dest = new Object[src.length + 1];
// 将新元素放到新数组的指定位置
dest[index] = s;
// 将源数组中下标<index,拷贝到新数组相同的下标位置
for (int i = 0; i < index; i++) {
dest[i] = src[i];
}
// 将源数组中其他下标的元素拷贝到新数组下标+1的位置
for (int i = index; i < src.length; i++) {
dest[i + 1] = src[i];
}
// 将src指向新数组
src = dest;
} else {
System.out.println("指定的下标超出范围!!!");
}
}
/**
* 删除指定位置的元素
*
* @param index
* 要删除的元素的下标
*/
public void delete(int index) {
if (index >= 0 && index < size()) {
// 定义新数组,长度是原始数组长度-1
Object[] dest = new Object[src.length - 1];
// 如果下标<index,则按下标位置拷贝
for (int i = 0; i < index; i++) {
dest[i] = src[i];
}
// index位置的值丢掉不需要拷贝
// >index的下标位置拷贝到新数组下标-1的位置
for (int i = index + 1; i < src.length; i++) {
dest[i - 1] = src[i];
}
// 将src指向新数组
src = dest;
} else {
System.out.println("指定的下标超出范围!!!");
}
}
/**
* 获得容器中元素个数的方法 容器中不为null的元素个数
*
* @return 返回元素的个数
*/
public int size() {
return len;
}
}
这样就很好的解决了,分配大了浪费空间,小了容量不够,还有某些for循环的效率不高等问题,泛型的优点和好处在于使用泛型定义类在声明该类对象时可以根据不同的需求指定<E>真正的类型,而在使用类中的方法传递或返回数据类型时候将不在需要进行类型转换操作而是使用在声明泛型对象时<E>中设置的类型,通过下面例子来加深理解
//定义泛型类
public class OverClass <E>{
//定义泛型成员变量
private E over;
//设置getxxx()方法
public E getOver(){
return over;
}
//设置setxxx()方法
public void setOver(E over){
}
public static void main(String[] args){
//实例化一个Boolean型对象
OverClass<Boolean> over = new OverClass<Boolean>();
//实例化一个Float对象
OverClass<Float> over1 = new OverClass<Float>();
//不需要进行类型转换
over.setOver(true);
over1.setOver(12.3f);
//不需要进行类型转换
Boolean b =over.getOver();
Float f = over1.getOver();
System.out.print(b);
System.out.print(f);
}
}
其实以上例子还可已不用泛型也能写出,但是经常在调用方法时候会出现“向上转型”和“向下转型”的问题;大家都知道在java中向上转型是安全的向下转型会出问题有可能出现异常,所以泛型就很好的解决了这一问题,在这里就不举例说明了,泛型的常规用法读者可以参考API文档自己摸索,这里不多做解释,在下一篇说明集合类以后,会将集合和泛型综合说明,