17、泛型

17_泛型

1、泛型
1.1 方法重载
1、要求在同一个类中 或者同一个接口内
2、要求方法名必须一致
3、要求方法形式参数列表必须不一致 调用方法的过程中通过实际参数列表的数据类型选择合适的方法

作用:
	1、降低方法冗余
	2、提高方法处理的多样性

代码演示

public class Demo1 {
	public static void main(String[] args) {
		print(10);
		print(11.0);
	}

	public static void print(int num) {
		System.out.println(num);
	}
	
	public static void print(double num) {
		System.out.println(num);
	}
}

1.2 泛型语法规则
格式:
	<自定义无意义单一大写英文字母泛型占位符> 泛型声明

常用的占位符
	<T> Type 类型
	<E> Element 元素
	<K> Key 键
	<V> Value 值
	<R> Return 返回值

泛型可以用到的位置
	1、泛型直接约束方法
	2、泛型约束类 类内的成员方法可以使用类声明泛型
	3、泛型约束接口 接口内的成员方法可以直接使用接口声明泛型

简单的泛型案例

public class Demo2 {
	public static void main(String[] args) {
		/*
		 * 方法形式参数列表数据类型 T 对应的具体数据类型 是由实际参数决定的
		 */
		print(10);
		print(false);
		print(11.0);
		print(12.0F);
	}

	/**
	 * 带有泛型约束的方法
	 * 
	 * @param <T> 自定义泛型声明
	 * @param t 泛型对应类型参数
	 */
	public static <T> void print(T t) {
		System.out.println(t);
	}
}

1.3 自定义泛型 约束方法
首先必须有泛型声明 告知编译器当前方法使用自定义泛型
格式:
	权限修饰符 是否静态 <泛型占位符> 方法名(形式参数列表)

【注意】
形式参数列表中必须有一个参数对应自定义泛型 用于明确泛型对应的具体数据
public class Demo3 {
	public static void main(String[] args) {
		//实际参数类型为 int 类型
		test(10);
		//Integer 是 int 类型的包装类
		Integer i = getType(11); 
		System.out.println(i);
		
		//实际参数为 Demo3 类型
		//匿名对象直接作为方法的参数
		test(new Demo3());
		Demo3 d3 = getType(new Demo3());
		System.out.println(d3);
		
		//实际参数为字符串类型
		test("字符串");
		String str = getType("字符串");
		System.out.println(str);
		System.out.println(getType("123"));
	}
	
	/**
	 * 方法参数使用了自定义类型 泛型对应的具体数据类型由实际参数类型决定
	 * 
	 * @param <T> 自定义泛型声明
	 * @param t 泛型参数 使用用户提供的实际参数 约束泛型对应的具体数据类型
	 */
	public static <T> void test(T t) {
		System.out.println(t);
	}
	
	/**
	 * 方法参数和返回值都使用了方法声明的自定义泛型 
	 * 要求方法参数中的泛型参数约束
	 * 
	 * @param <T> 自定义泛型声明
	 * @param t 泛型参数 使用用户提供的实际参数 约束泛型对应的具体数据类型
	 * @return 自定义泛型类型 泛型对应的具体数据类型由实际参数数据类型决定
	 */
	public static <T> T getType(T t) {
		return t;
	}
}

1.4 自定义泛型 约束类
格式:
	class 类名<自定义泛型占位符> {
		成员变量
		成员方法
		构造方法
	}

类声明的自定义泛型用于成员方法使用数据类型约束
/**
 * 自定义类型 带有自定义泛型
 * 【注意】
 * 	一个类带有自定义泛型 泛型对应的具体数据类型 由实例化对象过程约束
 * 
 * @author Echo
 *
 * @param <T> 自定义泛型
 */
class TypeA<T> {
	/**
	 * 成员方法可以使用类名声明的自定义泛型类型 无需再次声明
	 * 
	 * @param t 自定义泛型
	 */
	public void test(T t) {
		System.out.println(t);
	}
	
	/**
	 * 成员方法 方法和返回值类型都是类名声明的自定义泛型
	 * 
	 * @param t 自定义泛型
	 * @return 自定义泛型
	 */
	public T getType(T t) {
		return t;
	}
	
	/*
	 * static 修饰的静态成员方法不可以直接使用类名声明的自定义泛型 
	 * 
	 * 类名声明的泛型需要实例化对象 而静态成员方法和对象无关
	 * static 修饰的静态成员方法 和类对象无关 无法在类对象实例化过程中明确数据类型
	 * static 修饰的静态成员方法 在类文件加载的时候就需要准备就绪 而泛型的具体数据类型在类文件加载阶段不明确 无法使用
	 */
} 

public class Demo4 {
	public static void main(String[] args) {
		//实例化独对象过程中 约束当前 TypeA t1 对象使用泛型对应的具体数据类型为 Strig 类型
		TypeA<String> t1 = new TypeA<String>();
		
		//所有带有泛型 <T> 占位符对应的位置都是 String 类型 
		t1.test("字符串");
		System.out.println(t1.getType("字符串 String 类型"));
		
		//实例化独对象过程中 约束当前 TypeA t1 对象使用泛型对应的具体数据类型为 Integer 类型
		TypeA<Integer> t2 = new TypeA<Integer>();
		
		//所有带有泛型 <T> 占位符对应的位置都是 Integer 类型 
		t2.test(10);
		System.out.println(t2.getType(11));
		
		//实例化 TypeA 类对象 没有约束泛型对应的具体数据类型 有警告
		//t3 为 Object 类型
//		TypeA t3 = new TypeA();
		
		/*
		 * Object 类型是 Java 中所有类型的父类 是 Java 最大数据类型
		 * 
		 * 带有自定义泛型约束的类 没有在实例化对象的过程中 明确泛型对应的具体数据类型 
		 * 所有泛型对应的位置都是 Object 类型
		 */
//		t3.test(1);
//		t3.test('B');
//		t3.test("Object");
//		t3.test(new Demo4());
//		
//		Object o1 = t3.getType(10);
//		Object o2 = t3.getType("字符串");
	}
}

1.5 自定义泛型 约束接口
格式:
	interface 接口名<自定义泛型占位符> {
		成员方法
		default 修饰的默认方法
	}

【注意】
接口中的成员变量不能使用自定义泛型
1.5.1 泛型对应的具体数据类型由实现类实例化过程中自行决定
//自定义泛型约束接口

interface A<T> {
	//接口中缺省属性为 public abstract 的成员方法可以使用接口声明自定义泛型
	void test(T t);
	
	T getType(T t);
	
	//default 关键字修饰的默认方法可以使用接口声明自定义泛型
	default void testDefault(T t) {
		System.out.println(t);
	}
}

/*
 * 类实现自定义泛型接口
 * 1、泛型对应的具体数据类型由实现类实例化过程中自行决定
 * 2、泛型对应的具体数据类型在类实现接口的过程中直接约束
 */

/**
 * 1、泛型对应的具体数据类型由实现类实例化过程中自行决定
 * 
 * @author Echo
 *
 * @param <T> 自定义泛型
 */
class TypeB<T> implements A<T> {
	@Override
	public void test(T t) {
		System.out.println(t);
	}
	
	@Override
	public T getType(T t) {
		return t;
	}
}

public class Demo5 {
	public static void main(String[] args) {
		//实例化 TypeB 对象 泛型约束为 String 类型
		TypeB<String> t1 = new TypeB<String>();
		
		/*
		 * t1 对象对应的方法所有泛型位置都是 String 类型
		 * 包括接口中缺省属性为 public abstract 的成员方法
		 * 和 default 修饰的默认方法
		 */
		t1.test("接口实现类实现的接口中的方法 参数泛型目前对应的数据类型为 String 类型");
		t1.testDefault("接口中的 default 修饰的默认方法 方法泛型对应的具体数据类型根据当前实例化对象 t1 的数据类型 String 类型");
		String str = t1.getType("接口实现类实现的接口中的方法 方法参数和返回值类型对应具体数据类型 String 类型");
		System.out.println(str);
		
	}
}

1.5.2 泛型对应的具体数据类型在类实现接口的过程中直接约束
//自定义泛型约束接口
/*
 * 格式:
 * interface 接口名<自定义泛型占位符> {
 * 		成员方法 缺省属性:public abstract
 * 		default 修饰的默认方法: JDK 1.8 版本及以上
 * }
 */
interface B<T> {
	//接口中缺省属性为 public abstract 的成员方法可以使用接口声明自定义泛型
	void test(T t);
	
	T getType(T t);
	
	//default 关键字修饰的默认方法可以使用接口声明自定义泛型
	default void testDefault(T t) {
		System.out.println(t);
	}
}

/*
 * 1、泛型对应的具体数据类型由实现类实例化过程中自行决定
 * 2、泛型对应的具体数据类型在类实现接口的过程中直接约束
 */

/**
 * 2、泛型对应的具体数据类型在类实现接口的过程中直接约束
 * 
 * @author Echo
 *
 * @param <T> 自定义泛型
 */
class TypeC implements B<String> {
	@Override
	public void test(String t) {
		System.out.println(t);
	}
	
	@Override
	public String getType(String t) {
		return t;
	}
}
public class Demo6 {
	public static void main(String[] args) {
		//实例化对象
		TypeC t1 = new TypeC();
		
		t1.test("接口在被类实现时明确为 String 类型");
		t1.testDefault("接口泛型在被类实现时明确为 String 类型");
		System.out.println(t1.getType("字符串"));
	}
}

1.6 总结
泛型:
	1、泛型主要目的是增强方法 是满足方法数据类型支持的多样性 都是严格遵循数据类型一致化要求
		一旦约束泛型对应的具体数据类型 数据类型无法修改
	2、泛型在单一约束方法
		【明确要求】方法参数必须有一个对应自定义泛型类型
	3、泛型在类声明中使用
		【明确要求】泛型对应的具体数据类型由实例化过程约束 不可以使用 Object
	4、泛型在接口声明中使用
		1> 泛型对应的具体数据类型由实现类实例化过程中自行决定
		2> 泛型对应的具体数据类型在类实现接口的过程中j接口直接约束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值