泛型
泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数类型。
定义泛型类在"类名"后添加一对<>,里面定义"泛型名称";
格式:如ArrayList集合
class ArrayList< E > {
public boolean add(E e) { }
public E get(int index) { }
}
使用泛型类:创建对象时,确定泛型的类型
例如:ArrayList< String > list = new ArrayList< String >(); 此时相当于将E的类型替换为String类型。
例如:ArrayList< Integer > list = new ArrayList< Integer >(); 此时相当于将E的类型替换为Integer类型。
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.setName("张三");
System.out.println(s.getName());
Teacher t = new Teacher();
t.setAge(30);
// t.setAge("30");
System.out.println(t.getAge());
System.out.println("--------------");
Genericg1=new Generic();
g1.setT("张三");
System.out.println(g1.getT());
Genericg2=new Generic();
g2.setT(18);
System.out.println(g2.getT());
}
}
class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Teacher {
private Integer age;
public Teacher() {
}
public Teacher(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
class Generic{
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
结果:
张三 30 -------------- 赵四 18泛型方法 方法格式:
public static详细介绍T m1(T t1) { return t1; }
publicT genericMethod(T value)throws InstantiationException , IllegalAccessException{ return value; }
示例:
public class Test {
public static void main(String[] args) {
// Generic g = new Generic();
// g.show("张三");
// g.show(18);
// g.show(true);
// g.show(13.14);
// Generic g1 = new Generic();
// g1.show("赵四");
// Generic g2 = new Generic();
// g2.show(18);
// Generic g3 = new Generic();
// g3.show(true);
Generic g=new Generic();
g.show("张三");//String
g.show(18);//int
g.show(true);//boolean
g.show(13.14);//double
}
}
//class Generic {
// public void show(String s) {
// System.out.println(s);
// }
//
// public void show(Integer i) {
// System.out.println(i);
// }
//
// public void show(Boolean b) {
// System.out.println(b);
// }
//}
//泛型类改进
//class Generic {
// public void show(T t) {
// System.out.println(t);
// }
//}
//泛型方法改进
class Generic {
public void show(T t) {
System.out.println(t);
}
}
结果:
张三 18 true 13.14泛型接口 接口格式
泛型不仅可以声明泛型类,也可以声明泛型接口,声明泛型接口和声明泛型类的语法相似,也是在接口名称后面加< T >
格式:权限修饰符 interface 接口名<泛型标示符>{}
public class Test {
public static void main(String[] args) {
Generic g1 = new GenericTmpl();
g1.show("张三");
Generic g2 = new GenericTmpl();
g2.show(18);
Generic g3 = new GenericTmpl();
g3.show(true);
}
}
interface Generic {
public void show(T t);
}
class GenericTmpl implements Generic {
@Override
public void show(T t) {
System.out.println(t);
}
}
泛型接口实现方式
方式一:
子类继续定义泛型类型,通过使用者来确定具体类型
然后使用泛型接口
public class Test {
public static void main(String[] args) {
Fan i = null; // 声明接口对象
i = new Zi("李四"); // 通过子类实例化对象
System.out.println("内容:" + i.getVal());
}
}
interface Fan { // 在接口上定义泛型
public T getVal(); // 定义抽象方法,抽象方法的返回值就是泛型类型
}
//子类继续定义泛型类型,有使用者来确定
class Zi implements Fan { // 定义泛型接口的子类
private T val; // 定义属性
public Zi(T val) { // 通过构造方法设置属性内容
this.setVal(val);
}
public void setVal(T val) {//通过方法参数确定
this.val = val;
}
public T getVal() {
return this.val;
}
}
方式二:
子类确定泛型类型
interface Info泛型通配符{ // 在接口上定义泛型 public T getVar(); // 定义抽象方法,抽象方法的返回值就是泛型类型 } class InfoImpl implements Info { // 子类确定泛型类型 @Override public String getVar() {//因为在类里面已经确定了泛型类型,所以约束了方法的泛型 return null; } }
类型通配符一般是使用?代替具体的类型参数
例如 List> 在逻辑上是List< String >,List< Integer > 等所有List<具体类型实参>的类
通配符的使用
public void show( List < ? > list ){ }:表示可以接收具有"任何泛型"的"List类型"的集合
泛型上限指定
< ? extends E >:只能指向具有E,或者其子类的泛型的对象
public void show( List < ? extends Student > list ){ }:表示只能接收具有"Student"或者"其子类"泛型的集合对象;
泛型下限指定
< ? super E >:只能指向具有E,或者其父类的泛型的对象
还可以看到
public void show( List < ? super Student > stuList ){ } :表示只能接受Student类和其父类的集合对象
public class Test {
public static void main(String[] args) {
List students = new ArrayList();
List teachers = new ArrayList();
List persons = new ArrayList();
List strings = new ArrayList();
// 可以调用
m1(strings);
m1(strings);
// 因为m2()方法中的参数已经限定了参数泛型上限为Person,
// String类型不在这个范围之内,所以会报错
// m2(strings);
// 类型通配符下限通过形如 List super Student>来定义,
// 表示类型只能接受Student及其三层父类类型,如Objec类型的实例。
//m3(teachers);
m3(persons);// 可以通过
}
public static void m1(List> data) {
}
public static void m2(List extends Person> data) {
}
public static void m3(List super Student> stuList) {
}
class Person {
}
class Student extends Person {
}
class Teacher extends Person {
}
}
泛型好处
可以消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。
1.类型安全
2.消除强制类型转换



