当前位置: 移动技术网 > IT编程>开发语言>Java > Java 笔记 21:modcount, 泛型

Java 笔记 21:modcount, 泛型

2020年07月31日  | 移动技术网IT编程  | 我要评论
@TOCmodcountmodCount:记录当前集合被修改的次数(1)添加(2)删除这两个操作都会影响元素的个数。当我们使用迭代器或foreach遍历时,如果你在foreach遍历时,自动调用迭代器的迭代方法,此时在遍历过程中调用了集合的add,remove方法时,modCount就会改变,而迭代器记录的modCount是开始迭代之前的,如果两个不一致,就会报异常,说明有两个线路(线程)同时操作集合。这种操作有风险,为了保证结果的正确性,避免这样的情况发生,一旦发现modCount

Java 笔记 21

modcount

modCount:记录当前集合被修改的次数

  • (1)添加
  • (2)删除
  • 这两个操作都会影响元素的个数。
  • 当我们使用迭代器或foreach遍历时,如果你在foreach遍历时,自动调用迭代器的迭代方法,
  • 此时在遍历过程中调用了集合的add,remove方法时,modCount就会改变,
  • 而迭代器记录的modCount是开始迭代之前的,如果两个不一致,就会报异常,
  • 说明有两个线路(线程)同时操作集合。这种操作有风险,为了保证结果的正确性,
  • 避免这样的情况发生,一旦发现modCount与expectedModCount不一致,立即保错。
  • 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:
  • 在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,
  • 否则在任何时间以任何方式对列表进行修改,
  • 迭代器都会抛出 ConcurrentModificationException。
  • 因此,面对并发的修改,迭代器很快就会完全失败,
  • 而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

泛型

泛型:JDK1.5之后引入的
*

  • 泛型:泛化的类型,参数化类型
  • 生活中:
  • 生产瓶子的厂商,只负责生产瓶子,不管你这个瓶子将来用来装什么。
  • 在超市中,大家看到的瓶子上都有标签(商标),表明这个瓶子中是什么。
  • 生产饮料、酒、调料的厂商买回这个瓶子后,在装东西时,就给这个瓶子加上商标(标签)。
  • 贴上标签后,下次看到时,就知道里面是什么,我可以放心的使用。
  • Java中:
  • 例如:在设计集合这个容器的数据结构时,不知道我们程序员会用它来装什么对象。
  • 可能用它装字符串对象,可能用它装Apple对象…
  • 在设计时不确定元素的类型,但是在使用时,程序员是知道类型的。
  • 现在需要一个方式,渠道,让使用者在使用这个集合等时,告知这个集合我里面装的是什么对象。这就需要泛型。
  • 现在在设计这个集合时,元素的类型不确定,所以我把这个类型用形参表示,让使用者用实参给我确定这个类型。
  • 因为它代表的是数据的类型,所以把这种形参称为类型形参和类型实参。
  • 泛型:包括类型形参和类型实参
  • 泛型:<类型>
  • 例如:,…

泛型的好处:

  • (1)安全
  • (2)避免类型转换

泛型的使用形式有2种:

  • 1、泛型类\泛型接口
  • 2、泛型方法
  • 一、泛型类/接口
  • 1、语法格式:
  • 【修饰符】 class 类名<泛型形参列表>{
  • }
  • 【修饰符】 interface 接口名<泛型形参列表>{
  • }
  • 例如:
  • public interface Collection 就是泛型形参列表
  • public class ArrayList 就是泛型形参列表
  • public class HashMap<K,V> <K,V>就是泛型形参列表
  • 我们看到在声明类或接口时,,<K,V>,,…都是泛型的形参列表
  • 这些E,K,V,T等代表的是某种元素的类型
  • ArrayList list = new ArrayList();
  • 此时:泛型的实参列表
  • //存储本组学员的姓名(key)和它的年龄(value)
  • HashMap<String,Integer> map = new HashMap<String,Integer>();
  • 此时:<String,Integer>是泛型的实参列表
  • 2、要求
  • 泛型实参必须是一个引用数据类型,不能是基本数据类型
  • 3、如何为泛型类、泛型接口指定泛型实参
  • (1)创建泛型类的对象时
  • Student chinese = new Student(“张三”,“优秀”);
  • (2)继承泛型类、泛型接口时可以指定泛型实参
  • class ChineseStudent extends Student
  • (3)实现泛型接口时,可以指定泛型实参
  • class Employee implements Comparable
public class TestGenericClass {
	@Test
	public void test1(){
//		ArrayList<int> list = new ArrayList<int>();//错误
		ArrayList<Integer> list = new ArrayList<Integer>();//对
	}
	
	@Test
	public void test2(){
		//语文老师
		Student<String> chinese = new Student<String>("张三","优秀");
		
		//数学老师
		Student<Double> math = new Student<Double>("张三",89.5);
		
		//英语老师
		Student<Character> english = new Student<Character>("张三",'A');
	}
	
	
	@Test
	public void test3(){
		//语文老师
		ChineseStudent c = new ChineseStudent("张三","优秀");
	}
}

/*
 * 自定义一个泛型类:
 * 定义一个“特殊”的学生类,学生类包含两个属性:姓名,成绩
 * 此时成绩的情况很复杂:
 * 语文老师在表示学生时:成绩登记为:优秀、良好、及格、不及格
 * 数学老师在表示学生时:成绩登记为:89.5 ....
 * 英语老师在表示学生时:成绩登记为:A,B,C,D...
 * 
 * <T>:泛型形参
 * T在这个Student当做就是score的类型,凡是需要表示score的类型的地方都用T
 */
class Student<T>{
	private String name;
	private T score;
	public Student(String name, T score) {
		super();
		this.name = name;
		this.score = score;
	}
	public Student() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public T getScore() {
		return score;
	}
	public void setScore(T score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + "]";
	}
	
}
//语文老师
class ChineseStudent extends Student<String>{

	public ChineseStudent() {
		super();
	}

	public ChineseStudent(String name, String score) {
		super(name, score);
	}
	
}

//接口:java.lang.Comparable<T>
class Employee implements Comparable<Employee>{
	private int id;
	private String name;
	public Employee(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + "]";
	}
	@Override
	public int compareTo(Employee o) {
		return this.id - o.id;
	}
	
}

4、泛型类或泛型接口上的<泛型形参>这个类型可以用在哪些地方?

  • (1)可以用于属性、方法的数据形参、局部变量等的类型
  • (2)不能用于静态成员上
  • 5、泛型类或泛型接口的泛型形参,可以设定上限
  • <T extends 上限>
  • T的类型实参只能上限本身或上限的子类
  • <T extends 上限1 & 上限2 & 。。。。>
  • 如果多个上限,都要满足
  • 6、 泛型的形参一般代表什么的类型?
  • ArrayList:这个E代表集合的元素的类型
  • Map<K,V>:这个K代表key的类型,V代表的value的类型
  • Comparable:这个T代表,要与当前对象比较的另一个对象的类型
  • Student:这个T代表成绩的类型
  • 7、如果在使用泛型类或泛型接口的时候,没有指定泛型实参,会怎么样?
  • 泛型被擦除,泛型被擦除后,泛型形参被解析为什么类型呢?
  • 被解析为泛型形参的第一个上限的类型。
  • (1)如果没有指定泛型形参的上限,就按照Object处理
  • (2)如果指定泛型形参的上限,就按照上限处理,如果有多个上限,多个上限用&连接,按照最左边的第一个上限处理(是左面第一个上限的类型,并满足多个上限)

二、泛型方法

  • 1、什么情况需要声明泛型方法?
  • (1)如果某个静态方法想要使用泛型,需要单独设计
  • 例如:java.util.Arrays数组工具类
  • public static List asList(T… a)
  •  T...是可变参数
    
  • (2)如果泛型类或泛型接口上的泛型形参不适用于某一个方法(可以是静态的,也可以是非静态),那么这个方法,可以单独设计泛型
  • 例如:java.util.Collection
  • public abstract T[] toArray(T[] a)
  • 2、泛型方法的语法格式
  • 【修饰符】 <泛型形参列表> 返回值类型 方法名(【数据形参列表】)
  • 3、泛型方法的<泛型形参列表>这个类型就用于当前方法的形参类型、返回值类型、局部变量,和其他方法无关
  • 4、泛型方法的类型形参,什么时候指定类型实参
  • 当你调用这个方法时,编译器会根据方法的实参的类型,来确定泛型的类型实参的具体类型
  • 5、泛型方法的<泛型形参列表>中的类型也可以指定上限
  • <T extends 上限>
  • T的类型实参只能上限本身或上限的子类
  • <T extends 上限1 & 上限2 & 。。。。>
  • 如果多个上限,都要满足
public class TestGenericMethod {
	public <T extends Number> T test(T t){
		//...
		return t;
	}
	
	@Test
	public void test03(){
		Integer num = test(1);
		
		Double d = test(1.0);
		
//		test("hello");//错的,因为String不符合Number的上限
	}
	
	@Test
	public void test02(){
		Collection<String> c = new ArrayList<String>();
		c.add("张三");
		c.add("李四");
		
		String[] arr = new String[2];
		String[] array = c.toArray(arr);//根据arr的数组类型,来确定返回值的T[]的类型
		
		Object[] all = new Object[2];
		Object[] array2 = c.toArray(all);//根据all的数组类型,来确定返回值的T[]的类型
	}
	
	@Test
	public void test01(){
		List<Integer> list1 = Arrays.asList(1,2,3,4,5);//根据1,2,3,4,5可以确定T是Integer类型
		
		List<String> list2 = Arrays.asList("hello","java");//根据"hello","java"确定T是String类型
		
	}
}

通配符:wildcard

  • 通配符:?
  • 1、<?>:代表可以是任意类型
  • 2、<? extends 上限>:?代表是上限或上限的子类
  • 3、<? super 下限>:?代表的是下限或下限的父类
  • 看java.util.Collections:集合工具类
  • (1)public static boolean disjoint(Collection<?> c1, Collection<?> c2)看c1和c2是否有交集,如果没有交集返回true

在这里插入图片描述

本文地址:https://blog.csdn.net/qq_40473204/article/details/107669505

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网