当前位置: 移动技术网 > IT编程>开发语言>Java > Java基础语法泛型

Java基础语法泛型

2020年07月31日  | 移动技术网IT编程  | 我要评论
/* * 泛型的使用形式有2种: * 1、泛型类\泛型接口 * 2、泛型方法 * * 一、泛型类/接口 * 1、语法格式: * 【修饰符】 class 类名<泛型形参列表>{ * } * 【修饰符】 interface 接口名<泛型形参列表>{ * } * * 例如: * public interface Collection<E> <E>就是泛型形参列表 * public class ArrayList<E..
 /*
 * 泛型的使用形式有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

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

相关文章:

验证码:
移动技术网