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

Java基础语法泛型

程序员文章站 2022-03-25 15:00:43
/* * 泛型的使用形式有2种: * 1、泛型类\泛型接口 * 2、泛型方法 * * 一、泛型类/接口 * 1、语法格式: * 【修饰符】 class 类名<泛型形参列表>{ * } * 【修饰符】 interface 接口名<泛型形参列表>{ * } * * 例如: * public interface Collection 就是泛型形参列表 * public class ArrayList
 /*
 * 泛型的使用形式有2种:
 * 1、泛型类\泛型接口
 * 2、泛型方法
 * 
 * 一、泛型类/接口
 * 1、语法格式:
 * 【修饰符】  class  类名<泛型形参列表>{
 * }
 * 【修饰符】  interface  接口名<泛型形参列表>{
 * }
 * 
 * 例如:
 * public interface Collection<E>  <E>就是泛型形参列表
 * public class ArrayList<E>       <E>就是泛型形参列表
 * public class HashMap<K,V>	   <K,V>就是泛型形参列表
 * 我们看到在声明类或接口时,<E>,<K,V>,<T>,<U>....都是泛型的形参列表
 * 这些E,K,V,T等代表的是某种元素的类型
 * 
 * ArrayList<String> list = new ArrayList<String>();
 * 此时:<String>泛型的实参列表
 * 
 *  //存储本组学员的姓名(key)和它的年龄(value)
 * HashMap<String,Integer> map = new HashMap<String,Integer>();
 *  此时:<String,Integer>是泛型的实参列表
 *  
 *  2、要求
 *  泛型实参必须是一个引用数据类型,不能是基本数据类型
 *  
 *  3、如何为泛型类、泛型接口指定泛型实参
 *  (1)创建泛型类的对象时 
 *  Student<String> chinese = new Student<String>("张三","优秀");
 *  (2)继承泛型类、泛型接口时可以指定泛型实参
 *  class ChineseStudent extends Student<String>
 *  (3)实现泛型接口时,可以指定泛型实参
 *  class Employee implements Comparable<Employee>
 */  
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>:这个E代表集合的元素的类型
 * Map<K,V>:这个K代表key的类型,V代表的value的类型
 * Comparable<T>:这个T代表,要与当前对象比较的另一个对象的类型
 * Student<T>:这个T代表成绩的类型
 * 
 * 7、如果在使用泛型类或泛型接口的时候,没有指定泛型实参,会怎么样?
 * 泛型被擦除,泛型被擦除后,泛型形参被解析为什么类型呢?
 * 被解析为泛型形参的第一个上限的类型。
 * (1)如果没有指定泛型形参的上限,就按照Object处理
 * (2)如果指定泛型形参的上限,就按照上限处理,如果有多个上限,多个上限用&连接,按照最左边的第一个上限处理
 */
public class TestGenericClass2 {
	@Test
	public void test02(){
		ArrayList list = new ArrayList();
		list.add("1");//泛型擦除,按照Object处理
		
		XueSheng x = new XueSheng("张三", 89);//XueSheng(String, Number) 
		
		AClass a = new AClass();
		a.test(1);//按照Nubmer处理
	}
	
	@Test
	public void test01(){
//		XueSheng<String> x = new XueSheng<String>("张三","优秀");//错误的,因为String不是Number或Number的子类
		
		XueSheng<Double> x1 = new XueSheng<Double>("张三",89.5);
		XueSheng<Integer> x2 = new XueSheng<Integer>("张三",89);
		XueSheng<Long> x3 = new XueSheng<Long>("张三",89L);
	}
}
//T的上限,
//T的类型实参要求,同时是Number的子类,还要实现Comparable和Serializable接口
class AClass<T extends Number & Comparable & Serializable>{
	public void test(T t){
		
	}
}

/*
 * 自定义一个泛型类:
 * 定义一个“特殊”的学生类,学生类包含两个属性:姓名,成绩
 * 此时成绩的情况很复杂:
 * 语文老师在表示学生时:成绩登记为:87
 * 数学老师在表示学生时:成绩登记为:89.5 ....
 * 
 * <T>:泛型形参
 * T在这个XueSheng当做就是score的类型,凡是需要表示score的类型的地方都用T
 * 
 * 此时想要限定这个T必须是一个数字,不能是字符串等其他类型
 */
class XueSheng<T extends Number>{
	private String name;
	private T score;
	public XueSheng(String name, T score) {
		super();
		this.name = name;
		this.score = score;
	}
	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 "XueSheng [name=" + name + ", score=" + score + "]";
	}
	
}


class MyClass<T>{
	private T t;//用于当做属性的数据类型
//	private static  T t2;

	public MyClass(T t) {//用于当做方法的数据形参的类型
		super();
		this.t = t;
	}

	//可以用于返回值的类型
	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}
	
	public void test(){
		T t;//局部变量的类型
	}

/*	public static T getT2() {
		return t2;
	}

	public static void setT2(T t2) {
		MyClass.t2 = t2;
	}*/
	
}

泛型方法:

/*
 * 二、泛型方法
 * 1、什么情况需要声明泛型方法?
 * (1)如果某个静态方法想要使用泛型,需要单独设计
 * 例如:java.util.Arrays数组工具类
 * public static <T> List<T> asList(T... a)
 * 		T...是可变参数
 * 
 * (2)如果泛型类或泛型接口上的泛型形参不适用于某一个方法(可以是静态的,也可以是非静态),那么这个方法,可以单独设计泛型
 * 例如:java.util.Collection<E>
 * public abstract <T> 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
 */
public class TestWildcards {
	@Test
	public void test05(){
		Collection<String> src = new ArrayList<String>();
		src.add("hello");
		src.add("world");
		Collection<Integer> dest = new ArrayList<Integer>();
		dest.add(1);
		dest.add(2);
		
	//	copy(src,dest);//把src中的"hello"、"world"添加的dest中,有问题
		
		Collection<Object> dest2 = new ArrayList<Object>();
		copy(src, dest2);//把src中的"hello"、"world"添加的dest2中,没问题    此时T是String,?是Object
	}
	/*
	 * 举例:
	 * 想要声明一个方法,可以把一个Collection集合src中的所有元素,添加到另一个Collection集合dest中
	 */
	public <T> void copy(Collection<T> src, Collection<? super T> dest){
		for (T object : src) {
			dest.add(object);
		}
	}
	
	
	
	@Test
	public void test04(){
		ArrayList<String> list1 = new ArrayList<String>();
//		printGraphic(list1);//错误的因为String不满足<? extends Graphic>
		
		ArrayList<Circle> list2 = new ArrayList<Circle>();
		printGraphic(list2);//因为Circle满足<? extends Graphic>
	}
	
	/*
	 * 举例:
	 * 想要声明一个方法,遍历一个里面装着图形对象的集合
	 */
	public void printGraphic(Collection<? extends Graphic> c){
		for (Graphic graphic : c) {
			System.out.println(graphic);
		}
	}
	
	
	@Test
	public void test03(){
		Collection<String> c1 = new ArrayList<String>();
		c1.add("hello");
		
		Collection<Integer> c2 = new ArrayList<Integer>();
		c2.add(1);
		
		System.out.println(Collections.disjoint(c1, c2));
	}
	
	@Test
	public void test01(){
		List<Integer> list = Arrays.asList(1,2,3,4);
		print(list);
	}
	
	/*
	 * 声明一个方法:这个方法可以用于遍历所有的Collection系列的集合
	 * 此时因为Collection是一个泛型接口,Collection<E>
	 * 如果此时不指定<E>的具体类型,会报警告,(1)方式一,抑制警告(2)方式二:用?来代表任意类型
	 * 因为此时不知道要被遍历的集合的元素类型是什么
	 */
	public void print(Collection<?> c){
		for (Object object : c) {
			System.out.println(object);
		}
	}
	
	//以前我们说Object可以接收任意类型对象,但是不代表Collection<Object>可以接收任意泛型实参的集合
	//Collection<Object>这么写,只能接收Collection<Object>,List<Object>...,即泛型实参必须是<Object>
/*	public void print(Collection<Object> c){
		for (Object object : c) {
			System.out.println(object);
		}
	}*/
	
	@Test
	public void test2(){
		Object str = new String();//是多态
//		ArrayList<Object> list = new ArrayList<String>();//错误的,不是多态
		
		ArrayList<Object> list1 = new ArrayList<Object>();
		ArrayList<String> list2 = new ArrayList<String>();
	}
}
//图形类
class Graphic{
	//...
}
//圆类
class Circle extends Graphic{
	//...
}
//矩形类
class Rectangle extends Graphic{
	//...
}

集合的工具类Collections

/*
 * java.util.Collections工具类:
 * (1)public static <T> boolean addAll(Collection<? super T> c,T... elements):把elements这些元素添加到c这个集合中
 * (2)public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key):在list集合中找出key,用二分查找法
 * 		此时要求list集合是有大小顺序
 *	 <? extends Comparable<? super T>>:list集合中的元素必须是实现Comparable接口,?可以是T或T的父类,这个父类实现现Comparable接口也可以
 *
 * (3)public static <T> int binarySearch(List<? extends T> list,T key,Comparator<? super T> c)
 * 		此时要求list集合是有大小顺序的,按照你指定的Comparator进行比较大小
 * <? extends T>:是T或T的子类,说明list中存的元素是T类型的对象或T类型的子类对象
 * <? super T>:这个比较器是为T或T的父类设计的比较器也可以
 * 
 * (4)public static <T> void copy(List<? super T> dest,List<? extends T> src):把src的元素复制到dest
 * 	src中存的是T或T的子类的对象
 *  dest要求元素类型是T或T的父类类型
 *  
 * (5)public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) 
 * <T extends Object & Comparable<? super T>>是max方法的泛型形参列表,泛型形参T,设定了上限,说明T必须继承Object并且要实现Comparable接口
 * max方法用于在coll集合中找出最大的元素,要求这个元素可比较大小,所以 要求T元素实现Comparable接口
 * 
 * <? extends T>:coll集合中存的是T或T的子类的对象
 * 
 * (6)public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp)
 * 如果coll中的元素不支持自然比较大小,那么用comp这个定制比较器比较元素的大小
 * 
 * (7)public static void reverse(List<?> list):可以反转任意的List集合元素 
 * 
 * (8)public static void shuffle(List<?> list):类似于洗牌
 * 
 * (9)public static <T> Set<T> singleton(T o):返回一个只有一个元素的Set集合
 * 
 * (10)public static <T extends Comparable<? super T>> void sort(List<T> list):用于给List集合排序
 * <T extends Comparable<? super T>>要求集合中的元素实现Comparable接口
 * 
 * (11)public static <T> void sort(List<T> list, Comparator<? super T> c):可以按照定制比较器排序
 * 
 * (12)public static void swap(List<?> list,int i,int j):交换list中[i]与[j]位置的元素,List<?>代表集合的元素可以是任意类型
 * 
 * (13)public static <T> List<T> synchronizedList(List<T> list):可以把一个线程不安全的list集合变成一个线程安全的list集合
 * 。。。
 * (14)public static <T> List<T> unmodifiableList(List<? extends T> list):把list集合变成一个不可修改的集合,只读的集合
 * 
 */
public class TestCollections {
	@Test
	public void test5(){
		List<Integer> list = Arrays.asList(1,2,3,4);
		System.out.println(list);
		
		//说明list是一个只读的集合
//		list.add(5);//UnsupportedOperationException
		System.out.println(list.getClass());//class java.util.Arrays$ArrayList不是java.util.ArrayList
	}
	
	@Test
	public void test4(){
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		
		System.out.println(list);
		
		Collections.shuffle(list);
		
		System.out.println(list);
	}
	
	@Test
	public void test3(){
		ArrayList<SubCircle> list = new ArrayList<SubCircle>();
		list.add(new SubCircle(1.2));
		list.add(new SubCircle(2.2));
		list.add(new SubCircle(3.2));
		
		//T是Circle类型
		//因为Graphic是Circle的父类,<? super T>
		//SubCircle是Circle的子类,满足<? extends T>
		Collections.binarySearch(list, new Circle(2.2), new Comparator<Graphic>(){

			@Override
			public int compare(Graphic o1, Graphic o2) {
				if(o1.getArea() > o2.getArea()){
					return 1;
				}else if(o1.getArea() < o2.getArea()){
					return -1;
				}
				return 0;
			}
			
		});
	}
	
	@Test
	public void test2(){
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(5);
		list.add(9);
		
		//此时的T是Integer
		//list的<Integer>,这个Integer
		int index = Collections.binarySearch(list, 4);
	}
	
	@Test
	public void test1(){
		//元素是1,2,3,4
		ArrayList<Integer> list = new ArrayList<Integer>();
		ArrayList<String> list2 = new ArrayList<String>();
		ArrayList<Object> list3 = new ArrayList<Object>();
		ArrayList<Number> list4 = new ArrayList<Number>();
		
		//此时T是Integer类型,
		//<? super T>:可以是Integer或它的父类
		Collections.addAll(list, 1,2,3,4);
		
		//此时T是Integer类型,
		//因为String不满足<? super T>
//		Collections.addAll(list2, 1,2,3,4);
		
		//此时T是Integer类型,
		//Object满足<? super T>
		Collections.addAll(list3, 1,2,3,4);
		
		//此时T是Integer类型,
		//Nubmer满足<? super T>
		Collections.addAll(list4, 1,2,3,4);
	}
}
abstract class Graphic{
	public abstract double getArea();
}
class Circle extends Graphic{
	private double radius;

	public Circle(double radius) {
		super();
		this.radius = radius;
	}

	@Override
	public double getArea() {
		return Math.PI * radius * radius;
	}

	@Override
	public String toString() {
		return "Circle [radius=" + radius + "]";
	}
	
}
class SubCircle extends Circle{

	public SubCircle(double radius) {
		super(radius);
		
	}
}


本文地址:https://blog.csdn.net/kewu8971/article/details/107672227

相关标签: JavaSe java