想实现一个类存储数据,存储时可以像数组一样有数据的顺序,可以有下标方便获取数据 还可以无限存储,可修改可删除。
import java.util.Arrays;

/*
 * @author jun
 *
 */
public class MyList<T> {
	// 最终存储数据的还是数组
	T[] arr;
	int index = 0;

	public MyList() {
		arr = (T[]) new Object[5];
	}

	/**
	 * 添加元素
	 * @param t
	 */
	public void add(T t) {
		//判断是否超出数组长度,如果是则扩大长度
		if (index == arr.length) {
			arr = Arrays.copyOf(arr, arr.length + 5);
		}
		arr[index++] = t;
	}

	public T get(int i) {
		return arr[i];
	}

	/**
	 * 显示
	 */
	public void show() {
		StringBuffer str = new StringBuffer();
		for (int i = 0; i < index; i++) {
			if (i == index - 1) {
				str.append(arr[i]);
			} else {
				str.append(arr[i] + ",");
			}
		}
		System.out.println(str.toString());
	}

	/**
	 * 修改
	 * @param i
	 * @param t
	 */
	public void alter(int i, T t) {
		arr[i] = t;
	}

	/**
	 * 刪除
	 * @param i
	 */
	public void delete(int i) {
		for (; i < (index - 1); i++) {
			if (i + 2 == index) {
				arr[i + 1] = null;
			} else {
				arr[i] = arr[i + 1];
			}
		}
		index--;
	}

	public static void main(String[] args) {
		MyList<Object> list = new MyList<Object>();
		list.add("1");
		list.add(null);
		list.add("hellow");
		list.add(1);
		list.add(new MyList());
		list.add(new int[2]);
		list.add("1");
		list.show();
		System.out.println(list.get(4));
		list.delete(4);
		list.alter(1, 6);
		list.show();
	}
}
一、泛型:
  • 泛指的类型,可以代表任意类的
    可以在类的后面指定泛型 public class 类名<泛型>
    在类上面定义了泛型后,可以在当前类中的任意的位置使用当前的泛型,可以用在属性的类型、参数的类型、方法的返回值等等。
    当我们创建一个泛型类的对象时,需要给泛型指定具体的类型,例:声明泛型
    类名<具体类型(任何引用数据类型)> 对象 = new 类名<具体类型>();例:声明泛型
    当指定了具体的类型时,那么类中所有的泛型都变成指定的类型
    在创建对象时如果没有指定泛型的类型,那么泛型默认为Object类型
    类名 对象 = new 类名(); -->Object
声明泛型
class Point<T> { // 此处可以是任意的标识符号,T是type的简称
	private T var; // 此变量的类型由外部决定

	public T getVar() { // 返回值的类型由外部指定
		return var;
	}

	public void setVar(T var) {// 设置的类型由外部指定
		this.var = var;
	}
}

public class Test {
	public static void main(String[] args) {
		Point<Integer> p = new Point<Integer>(); // 里面的var类型为Integer类型
		p.setVar(30); // 设置数字,自动装箱
		System.out.println(p.getVar() * 2); // 计算结果,按数字取出
	}
}
}
二、泛型设置的要求

在泛型的指定中,是无法指定基本数据类型的,必须设置成一个类,这样在设 置一个数字的时候就必须使用包装类,而在JDK 1.5之后提供了自动装箱的操 作,操作时也不会太复杂。

三、指定多个泛型

如果一个类中有多个属性需要使用不同的泛型声明,则可以在声明类的时候指 定多个泛型类型。

class Notepad<K,V> { // 此处指定两个泛型类型 
	private K key;     // 此变量的类型由外部决定 
	private V value; // 此变量的类型由外部决定 
	public K getKey() { 
		return key; 
		} 
	public void setKey(K key) { 
		this.key = key; 
		}
	public V getValue() { 
		return value; 
		}
	public void setValue(V value) {
		this.value = value; 
		} 
}
四、泛型的应用

1、泛型应用中的构造方法

  • 构造方法可以为类中的属性初始化,那么如果类中的属性通过泛型指定,而又 需要通过构造设置属性内容的时候,那么构造方法的定义与之前并无不同,不 需要像声明类那样指定泛型。
  • 使用格式:
    [访问权限] 构造方法 ([<泛型类型> 参数名称]){}

2、匹配任意类型的他通配符

  • 在开发中对象的引用传递是最常见的,但是如果在泛型类的操作中,在进行引 用传递的时候泛型类型必须匹配才可以传递,否则是无法传递的。
class Info<T> {
	private String var;

	public String getVar() {
		return var;
	}

	public void setVar(String var) {
		this.var = var;
	}

}
public class Test {
	
	public static void main(String[] args) {
		Info<String> i = new Info<String>(); // 指定String为泛型类型
		i.setVar("lisi");              // 设置字符串 
		fun(i);                     // 错误,无法传递 应传指定Object为泛型类型
		}

	public static void fun(Info<Object> temp){// 此处可以接收Object泛型类型的 Info对象 
		System. out.println("内容:" + temp); 
		}
}

3、使用通配符“?”

  • 以下程序在fun()方法中使用“Info<?>”的代码形式,表示可以使用任意的泛型类型对象,这 样做的话fun()方法定义的就比较合理了,但是在使用以上语法的时候也有一个注意点,即: 如果使用“?”接收泛型对象的时候,则不能设置被泛型指定的内容
class Info<T> {
	private String var;

	public String getVar() {
		return var;
	}

	public void setVar(String var) {
		this.var = var;
	}

}
public class Test {
	
		public static void main(String[] args) { 
			Info<String> i = new Info<String>() ; // 指定String为泛型类型 
			i.setVar("lisi") ;              // 设置字符串 
			fun(i) ;                     // 传递 String为泛型类型
			}
		public static void fun(Info<?> temp){// 此处可以接收任意泛型类型的 Info对象 
			System.out.println("内容:" + temp.getVar()); 
		}
}

4、受限泛型

  • 在引用传递中,泛型操作中也可以设置一个泛型对象的范围上限和范围下限。 范围上限使用extends关键字声明,表示参数化的类型可能是所指定的类型, 或者是此类型的子类,而范围下限使用super进行声明,表示参数化的类型可 能是所指定的类型,或者是此类型的父类型,直至Object类。
  • 设置上限:
    声明对象:类名称<? extends 类> 对象名称
    定义类:[访问权限] 类名称<泛型标识 extends 类>{}
    设置下限:
    声明对象:类名称<? super 类> 对象名称
    定义类:[访问权限] 类名称<泛型标识 extends 类>{}
    * 注意
    一个类的子类可以通过对象多态性,为其父类实例化,但是在泛型操作中,子 类的泛型类型是无法使用父类的泛型类型接收,例如:Info 不能使 用Info

5、定义泛型接口

  • 在JDK 1.5之后,不仅仅可以声明泛型类,也可以声明泛型接口,声明泛型接 口和声明泛型类的语法类似,也是在接口名称后面加上,如下格式所示:
  • [访问权限] interface 接口名称<泛型标识>{}
interface Info<T>{ // 在接口上定义泛型 
public T getVar() ; 
}
  • 泛型接口的两种实现方式
    泛型接口定义完成之后,下面就要定义此接口的子类,定义泛型接口的子类时 有两种方式,一种是直接在子类之后声明泛型,另外一种是直接在子类实现的 接口中明确的给出泛型类型。
  • 实现1 ——— 在子类的定义上声明泛型类型
interface Info<T>{         // 在接口上定义泛型 
	public T getVar() ; 
	} 
class InfoImpl<T> implements Info<T>{// 定义泛型接口的子类 
	private T var;        // 定义属性 
	public InfoImpl(T var){     // 通过构造方法设置属性内容 
	this.setVar(var); 
	} 
public void setVar(T var){ 
	this.var = var ; 
	} 
public T getVar(){ 
	return this.var ; 
	} 
}
  • 实现2 ——— 直接在接口中指定具体类型
interface Info<T>{ // 在接口上定义泛型 
	public T getVar() ; 
	} 
class InfoImpl implements Info<String>{// 定义泛型接口的子类,指定类型为String 
	private String var ; // 定义属性 
	public InfoImpl(String var){// 通过构造方法设置属性内容 
		this.setVar(var) ; 
		} 
	public void setVar(String var){ 
		this.var = var ; 
		} 
	public String getVar(){ // 接口上已指明类型,所以此处必须是String 
		return this.var ; 
		} 
	}

6、定义泛型方法

  • 泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型,使用 如下的格式定义泛型方法。
  • 泛型方法的简单定义:
    [访问权限] <泛型标识> 返回值类型 方法名称([泛型标识 参数名称])
  • 通过泛型方法返回泛型类实例
    如果现在希望可以通过泛型方法返回一个泛型类的实例化对象的话,则必须在 方法的返回类型声明处明确的指定泛型标识。
  • 使用泛型统一传入的参数类型
class Info<T> {
	private T var; // 此变量的类型由外部决定

	public T getVar() { // 返回值的类型由外部指定
		return var;
	}

	public void setVar(T var) {// 设置的类型由外部指定
		this.var = var;
	}

	public String toString() { // 覆写Object类中的toString()方法
		return this.var.toString();
	}
}

public class Test {
	public static void main(String args[]) {
		Info<String> i1 = new Info<String>(); // 设置String为泛型类型
		Info<String> i2 = new Info<String>(); // 设置String为泛型类型
		i1.setVar("HELLO"); // 设置内容
		i2.setVar("lisi"); // 设置内容
		add(i1, i2);
	}

	public static <T> void add(Info<T> i1, Info<T> i2) {
		System.out.println(i1.getVar() + " " + i2.getVar());
	}
}

7、泛型数组

  • 使用泛型方法时,也可以传递或返回一个泛型数组,如下代码所示。
public class Test {
	public static void main(String args[]) {
		Integer i[] = fun1(1, 2, 3, 4, 5, 6); // 返回泛型数组
		fun2(i); // 输出数组内容
	}

	public static <T> T[] fun1(T... arg) { // 接收可变参数,返回泛型数组
		return arg; // 返回泛型数组
	}

	public static <T> void fun2(T param[]) { // 接收泛型数组
		System.out.print("接收泛型数组:");
		for (T t : param) {
			System.out.print(t + "、");
		}
		System.out.println();
	}
}

8、泛型的嵌套设置

  • 可以在一个类的泛型中指定另外一个类的泛型。
class Info<T, V> {// 指定两个泛型类型
	T string;
	V i;

	public Info(T string, V i) {
		this.string = string;
		this.i = i;
	}

	public T getValue() {
		return string;
	}

	public V getVar() {
		return i;
	}
}

class Demo<S> {
	S i;

	public Demo(S i) {
		this.i = i;
	}

	public S getInfo() {
		return i;
	}
}

public class Test {
	public static void main(String args[]) {
		Demo<Info<String, Integer>> d = null;// 将Info作为Demo的泛型类型
		Info<String, Integer> i = null;// Info要指定两个泛型类型
		i = new Info<String, Integer>("李四", 30);
		d = new Demo<Info<String, Integer>>(i);// 在Demo类中设置Info类对象
		System.out.println("内容一:" + d.getInfo().getVar());
		System.out.println("内容二:" + d.getInfo().getValue());
	}
}