欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java 笔记 21:modcount, 泛型

程序员文章站 2022-10-03 14:29:30
@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

Java 笔记 21:modcount, 泛型

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