Java基础学习之泛型

一泛型

泛型: 标识着集合中保存的元素是什么类型.

泛型的好处:

1.操作数据更加安全(规范集合中能保存的数据)

2.可以避免向下强转类型的麻烦

3.将运行时的错误转到编译时报错



--泛型类

在类的声明上添加泛型 ,使用字母 可以随意一个字母,不考虑大小写


看一个例子 我们定义一个工人类
public class Worker<Z> {
	// 声明成员变量
	private Z z;
	//声明成员方法 set get

	public Z getZ() {
		return z;
	}

	public void setZ(Z z) {
		this.z = z;
	}

如上,我们通过泛型定义,能够使代码得到复用.我们可以将Z 替换成任何我们想要的类型

Worker<Integer> integerWorker = new Worker<Integer>();
Worker<Double> doubleWorker = new Worker<Double>();
Worker<String> stringWorker = new Worker<String>();

类上声明的泛型 会在创建对象时 被赋值真正的类型.另外一个类中可以声明对个泛型

--泛型方法

声明方式 :声明一个泛型方法很简单,只要在返回类型前面加上一个类似<W>的形式就行了:

public<W> void fun( W w)
	{
		System.out.println(w);
	}
如果你在方法声明了新的泛型,该泛型会在该方法调用的时候 赋值泛型 需要在方法中声明泛型.

--静态方法的泛型

public static<N> void sayHi(N n) {
     System.out.println(n);
}

不能直接使用类声明的泛型 ,直接使用类型调用静态方法时,没有对象的创建,  Z泛型还没有被赋值.

使用泛型时,可以单独声明一下 如上的例子加在修饰符后.

另外接口也可以使用泛型

// 泛型接口
 interface InterA<M>{
	public abstract void fun(M m);
 }


//实现类
class InterAImpl implements InterA<String>{

	@Override
	public void fun(String m) {
		// TODO Auto-generated method stub
		
	}

---泛型遍历集合

--好处2可以避免向下强转类型的麻烦

public static void fun() {
		// 泛型 前后要保持一致
		//JDK 1.7 菱形泛型 : 可省略后面的泛型
		ArrayList<String> arrayList = new ArrayList<>();
		arrayList.add("a");
		arrayList.add("b");
		arrayList.add("c");
		arrayList.add("d");
		
		//遍历集合
		ListIterator<String> listIterator = arrayList.listIterator();
		//正向遍历
		while (listIterator.hasNext()) {
			//获取集合中的元素
			String string = (String) listIterator.next();
			System.out.println(string);
		}
		System.out.println("<------------------------->");
		//逆向遍历时 要先正向遍历将迭代器指针移到集合最下方	
		while (listIterator.hasPrevious()) {//判断前一个元素是否存在
			//获取前一个元素
			String string = (String) listIterator.previous();
			System.out.println(string);
		}
	}
--好处3  将运行时的错误转到编译时报错
public static void fun2() {
		//不加泛型保存3个学生
		
		ArrayList<Student> list = new ArrayList<>();
		list.add(new Student("空", 20));
		list.add(new Student("凸", 15));
		list.add(new Student("海", 14));
		
		//从集合中取出一个元素
		Object object = list.get(0);
		Student student = (Student)object;
		System.out.println(student.getName());
		// 从集合中 取出一个元素 强转工人类型
		//调用工人的工作方法
		
		//元素类型你可以 随意强转 没有约束
		//编译时不报错
		
		// 加上泛型 可以在编译的时候 有错误提示  让集合保存的元素 更加安全.
//		Worker worker = (Worker) list.get(1);  
//		worker.work();
	}

二 多参数的参数

public static void fun4() {
		//数组转集合
		int [] array = {1,2,3,4,5};
		//根据泛型 这个集合中每一个元素都是数组
		List<int[]> list = Arrays.asList(array);
		System.out.println(list);
	//直接传入int数组 系统不会帮你 自动装箱
		//直接把数组中元素放入集合中.
		Integer [] newArray = {1,2,3,4,5};
		List<Integer> asList = Arrays.asList(newArray);
		System.out.println(asList);
	}
public static void fun5() {
		// 调用多参数数组
		int [] array= {1,3,2,5};
	 fun4(2,array);//方式一
//     fun4(0,8,7,2,6,2);//方式二
	}
	// int ...num 这个参数可以看成一个数组
	//可以当做数组遍历  使用方式
	//1. 直接传入一个数组
	//2.可以传多个数用逗号分开
	//注意: 同类型多参数时 最好把多参数放到最后
	public static void fun4(int a,int ...num ) {
		for (int i = 0; i < num.length; i++) {
			System.out.println(num[i]);	
		}
		System.out.println(a);
	}

三 泛型 <? extends E>

addAll 就是利用这个类型
 ?是子类 E是父类 ,只能使用父类的子类 或者本类.也叫向下限定
public static void fun1() {
		//	addAll(Collection<Student extends Person> c) 
		//创建一个person 集合
		ArrayList<Person> list1 = new ArrayList<>();
		list1.add(new Person("wang1",11));
		list1.add(new Person("wang2",11));
		//创建一个student集合 保存两个student
		ArrayList<Student>  list2 = new ArrayList<>();
		list2.add(new Student("heh", 10));
		list2.add(new Student("hew", 10));
		
		list1.addAll(list2);
		System.out.println(list1);
//		list2.addAll(list1);
	}
上面的例子中student 是 person 类的子类 ,所以
list1.addAll(list2); 是OK的
list2.addAll(list1); 是错误的.

删除循环

public static void fun2() {
		//循环删除
		//创建一个元素保存 a b c d
		//删除b (使用循环)
		ArrayList<String> List = new ArrayList<>();
		List.add("a");//0
		List.add("b");//1
		List.add("b");//2
		List.add("c");//3
		List.add("d");//4
		for (int i = 0; i < List.size(); i++) {
			if (List.get(i).equals("b")) {
				//是 b 就删了
				// 删除后 要退回角标
				List.remove(i--); 
			}
		}
		System.out.println(List);
	}
List.remove(i); 
a b c d
List.remove(i--); 
a c d

在循环时, 集合长度变化,当索引值为1的"b" 被删除后 索引为2的"b" 的索引则变成1 i++之后,第二的b就无法被删除了.

另外使用迭代器也能避免这种问题

public static void fun3() {
		//迭代器删除
		ArrayList<String> List = new ArrayList<>();
		List.add("a");//0
		List.add("b");//1
		List.add("b");//2
		List.add("c");//3
		List.add("d");//4
		ListIterator<String> listIterator  = List.listIterator();
		while (listIterator.hasNext()) {
			String string = (String) listIterator.next();
			if (string.equals("b")) {
				listIterator.remove();
				//迭代器中需要使用
				//迭代器类中的删除方法
				//避免出现并发修改异常
			}
		}
		System.out.println(List);
	}

猜你喜欢

转载自blog.csdn.net/vlin_fan/article/details/80396409