泛型(类型参数):泛型设计编写代码意味着代码可以被不同类型的对象重用,【个人理解:将类型参数化,实际调用类型由实例化对象或方法调用的对象为准】
泛型基础定义演示:
package Generic;
/**
* 测试泛型,泛型擦除 属性类型: 子类中由子类确定。 基类中由基类确定 方法重写: 随基类确定
*
* @author Administrator
*
*/
public class GenericTest {
public static void main(String[] args) {
// 创建中学类
Middle<String, String> middle = new Middle<>();
// see方法需要传入String对象
middle.see("中学生在看");
// 查看属性id是String类型,子类中属性由子类类型
middle.getId();
Primary<String, String> primary = new Primary<>();
// Priamry类进行了类型擦除,see方法需要传入Object对象,重写的方法由基类确定
primary.see("小学生在看");
// 查看属性id是String类型
primary.getId();
// 调用泛型方法,传入一个字符串,确定了泛型方法的类型
Exam exam = new Exam();
exam.exam("exam");
Middle<Object, Object> middleMath = new Middle<Object, Object>();// 使用Object类替换类型
Middle middleMathTest = new Middle();// 泛型擦除后,使用Object替换,但是不会进行类型检查,所以传入的不会报错
// exam.examMath(middleMath);
// 报错,需要的是参数类型是String类型的中学生类型,但是传入的是参数类型是Object类型的学生类型
exam.examMath(middleMathTest);
Student<String, Student> ploymorphic = new Middle<String, Student>();
// 泛型:类型参数不能使用多态,报错
// Student<String,Student> ploymorphicone = new Middle<String,Middle>();
Middle<String, String> array = new Middle<String, String>();
// 泛型不能使用数组,但是可以声明泛型数组,若需要赋值,需要类型转换
// Middle<String, String>[] array = new Middle<String,String>[] ();
String[] str = new String[] {"a","b","c"};
//如果需要使用泛型数组功能选用类型转换
Array<String> array1 = new Array<String>(str);
int length = array1.arry.length;
System.out.println(length);
}
}
class Exam {
/**
* 泛型方法的定义
*
* @param stu
* 传入界定参数
*/
public <T> void exam(T stu) { // 泛型方法
System.out.println("这是一次测试");
}
public void examMath(Middle<String, String> stu) { // 泛型方法
System.out.println("这是一次测试");
}
}
class Array<T> {
Object[] arry = new Object[10];
/**
* 构造器传入指定类型的参数类型的数组,将产生一个Array实例的对象,其arry属性是指定类型的数组,可以设置方法调用
* @param arry
*/
@SuppressWarnings("hiding")
public <T> Array(T[] arry) {
this.array();
}
/**
* 使用Object类接受输入类,将其强制转换成相应的类型
* @return强制转型返回函数类型
*/
@SuppressWarnings("unchecked")
private T array(){
return (T)this.arry;
}
}
泛型类定义:
ackage Generic;
/**
* 泛型类,使用类型变量T,T1 ,定义为基类【抽象类】
*
* @author Administrator
*
* @param <T>
* @param <T1>
*/
public abstract class Student<T, E> {
private T name; // 引用泛型类型,声明属性
public Student() { // 空构造器
}
public Student(T name) {// 带参构造器
super();
this.name = name;
}
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
/*泛型方法
public abstract void run(T obj);// 抽象方法
public abstract <E> String see(E obj);// 抽象方法,带泛型抽象方法
}
泛型方法定义:
泛型变量的限定:
泛型类的继承:
package Generic;
/**
*
* 继承泛型Man,Man未进行泛型擦除
*
* @author Administrator
*
* @param <T>泛型:【参数类型】
* @param <T1>泛型:【参数类型】
*/
public class Middle<T, E> extends Student<T, E> {
private T id;
public Middle() { // 空构造器
}
public Middle(T id) {// 带参构造器
super();
this.id = id;
}
public Middle(T id, T name) {// 带参构造器
super(name);
this.id = id;
}
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
@Override
public void run(T obj) {// 重写run方法
System.out.println(obj);
}
@SuppressWarnings("hiding")
@Override
public <E> String see(E obj) {// 重写see方法
System.out.println(obj);
return null;
}
}
泛型擦出:
package Generic;
/**
* 继承泛型类Man,但是基类进行泛型擦除后,若泛型没有进行泛型限定,会用默认用Object类替换类型变量.
*
* @param id学生的id
* @param name学生的姓名
*/
class Primary<T, E> extends Student{
private T id;
public Primary() {
}
public Primary(T id) {
super();
this.id = id;
}
@SuppressWarnings("unchecked")
public Primary(T id, T name) {
super(name);
this.id = id;
}
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
public void run(Object obj) {// 重写run方法,Man类进行了泛型擦除,因无限定,提供一个自动类型:Obeject
System.out.println(obj);
}
@Override
public String see(Object obj) { // 重写run方法,Man类进行了泛型擦除,因无限定,提供一个自动类型:Obeject
// TODO Auto-generated method stub
return null;
}
}
泛型桥方法的使用(当使用泛型擦除后,子类对父类继承的方法存在两个一个是Object类型替换的,还有一个是子类本身泛型参数定义的参数,需要在父类继承继承方法重写,将两个方法合并):
泛型调用遗留代码:
泛型的约束和局限性: