0
点赞
收藏
分享

微信扫一扫

【java初学】泛型详解

梦想家们 2022-03-31 阅读 43

文章目录

泛型

1. 泛型

1.1 为什么要使用泛型
1. 泛型能够让代码更加具有普适性!!!
	例如昨天的排序算法,目前支持的有且只有Worker数据类型
	后期开发中,一定会涉及到很多种数据类型的排序,排序算法是一致的,不同的是排序规则,和排序处理的数据类型
	可以使用泛型来对数据类型进行更高层级的处理

2. 泛型可以减少没有必要的强制类型转换!!!
3. 泛型可以在满足数据类型多样化的情况下,通过一定的条件约束,能够做到足够的数据类型一致化要求。
1.2 泛型的基本格式
格式:
	<T> <E> <K> <V>
	<自定义无意义单个大写英文字母泛型占位符>

可以使用的地方
	1. 方法
	2. 类
	3. 接口

1.3 泛型在方法中使用

方法内使用自定义声明泛型
	【强制要求】
		方法使用的泛型,一定需要在参数中存在,用于约束当前方法使用的泛型占位符具
		体数据类型是哪一个
package com.qfedu.a;

public class Demo1 {
	public static void main(String[] args) {
		String str = testType("字符串");
		Integer i = testType(1);
		Demo1 d1 = testType(new Demo1());
		
	}
	
	/**
	 * 带有自定义泛型<T>的方法,需要的参数和返回值类型都是泛型T
	 * 【重点】 泛型的具体数据类型是需要通过实际参数来约束的
	 * 
	 * @param <T> 自定义泛型单个大写英文字母无意义占位符
	 * @param t 用户指定的数据类型,第一个是一个参数,第二用于约束T对应的具体数据类型
	 * @return 自定义泛型T 被约束之后的具体数据类型
	 */
	public static <T> T testType(T t) {
		System.out.println(t.getClass());
		return t;
	}

}
package com.qfedu.a;

public class Demo2 {
	
	public static void main(String[] args) {
		/*
		 * int 和 Integer 之间的关系
		 * Integer 这是一个类 是 int 数据类型的包装类
		 * 
		 * int 和 Integer可以无缝衔接,但是有一些不同之处。
		 */
		Integer[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
		
		printArray(arr);
		
		String[] strArr = {"七一建党", "八一建军", "十一国庆", "五一劳动", "六一儿童"};
		
		printArray(strArr);
	}
	
	public static <T> void printArray(T[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
}
1.3 泛型在类内的使用
格式:
	class 类名<自定义无意义单个大写字母占位符> {
		类内的非静态成员方法可以使用自定义泛型
	}
package com.qfedu.a;

/**
 * 当前类带有自定义泛型
 * 		当前自定义泛型可以在类内的方法使用
 * @author Anonymous
 *
 * @param <T>
 */
class TypeR<T> {
	public void test(T t) {
		System.out.println(t);
	} 
	
	public T getType(T t) {
		return t;
	}
	
	/*
	 * 静态方法是否可以使用类名声明的泛型
	 * 
	 * 静态成员方法在类文件的加载阶段需要明确所有的内容。
	 * 
	 * 类名声明的自定义泛型占位符是在创建类对象时,明确当前泛型
	 * 对应的具体数据类型是什么。
	 * 静态成员方法在类文件加载之后,已经可以通过类名直接调用。
	 * 
	 * 生命周期存在一定的时间差!!!
	 * 
	 */
	// public static T testStatic(T t) {	
	// }
	
	/* 
	 * 自娱自乐
	 * 
	 * 通常情况下,静态方法自定义泛型会考虑和类名声明泛型不冲突!!!
	 */
	public static <E> E testStatic(E e) {
		return e;
	}

}

public class Demo3 {
	public static void main(String[] args) {
		/*
		 * 创建一个带有自定义泛型的类对象,格式如下
		 * Eclipse中:
		 * 		TypeR<String> typeR = new TypeR<String>();
		 * IDEA 
		 * 		TypeR<String> typeR = new TypeR<>();
		 * 
		 * 明确告知编译器,当前类对象typeR 自定义泛型对应的具体数据类型为String类型
		 */
		TypeR<String> typeR = new TypeR<String>();
		// 类内所有使用到自定义泛型的位置都是String
		typeR.test("测试");
		String str = typeR.getType("大家注意身体");
		
		// 当前约束之后,方法内所有使用到泛型的位置,都是Integer类型
		TypeR<Integer> typeR2 = new TypeR<Integer>();
		typeR2.test(10);
		Integer type = typeR2.getType(10);
		
		TypeR typeR3 = new TypeR();
		/*
		 *  数据类型一致化!!!
		 *  
		 *  一个类带有自定义泛型,在创建对象的过程中,没有约束泛型的具体数据类型,泛型对应的所有
		 *  类型都是Object类型
		 *  这样做有悖于泛型的使用要求,泛型使用是为了 提供代码的普适性,可变通性,但是不能违背
		 *  数据类型一致化要求。
		 */
		typeR3.test('六');
		typeR3.test("就是这么牛");
		typeR3.test(new Demo1());
	}
}
1.4 泛型在接口中使用
格式:
	interface 接口名<自定义泛型占位符> {
		成员变量不得使用自定义泛型数据类型
			接口中成员变量缺省属性为public static final 
			final修饰的成员变量,定义时必须初始化,在泛型没有明确数据类型之前,
			无法针对当前数据类型进行合理的初始化操作。【不能使用】
		
		接口中的方法可以使用自定义泛型
        	缺省属性方法
        	default默认方法
	}
package com.qfedu.a;

interface A<T> {
	/**
	 * 类内的缺省属性为public abstract方法,当前方法的返回值和参数类型
	 * 都使用了自定义泛型
	 * 
	 * @param t 接口自定义的泛型数据类型 
	 * @return 接口自定义的泛型数据类型
	 */
	T testA(T t);
	
	/**
	 * 默认方法,default修饰方法,当前方法可以拥有方法体,该方法的返回值
	 * 和参数类型都是接口自定义泛型。
	 * 
	 * @param t 接口自定义的泛型数据类型
	 * @return 接口自定义的泛型数据类型
	 */
	default public T testDefault(T t) {
		return t;
	}
}

/*
 * 自由 Freedom
 * 
 * 类名声明和实现接口一致的泛型使用,泛型对应的具体数据类型是依赖于
 * 创建当前类对象时进行数据约束的。
 */
class TypeFreeDom<T> implements A<T> {

	@Override
	public T testA(T t) {
		System.out.println(t.getClass());
		return t;
	}

}

/*
 * 妻管严模式
 * 
 * 遵从接口的过程中,已经明确当前泛型对应的具体数据类型是什么'
 * 接下来所有接口中使用到泛型的方法,都是有接口之后的数据类型进行
 * 约束。
 */
class QFY implements A<String> {

	@Override
	public String testA(String t) {
		// TODO Auto-generated method stub
		return null;
	}
	
}

public class Demo4 {
	public static void main(String[] args) {
		TypeFreeDom<String> tf = new TypeFreeDom<String>();
		
		String testA = tf.testA("测试呢");
		String testDefault = tf.testDefault("测试默认方法");
		
		TypeFreeDom<Character> tf2 = new TypeFreeDom<Character>();
		
		tf2.testA('A');
		tf2.testDefault('A');
		
		new QFY().testA("围城");
		new QFY().testDefault("城堡");
	}
}
举报

相关推荐

0 条评论