目录
前言
认识JavaSE中泛型的基本规则,作用,和使用环境
一、简单理解泛型?
【泛型】 我们可以理解为广泛的类型,可以理解为 <> 为我们函数中的(),里面是参数列表,不过<> 中必须是引用类型。创建对象,调用方法时,指定类型。
二、引出泛型
1.看一个需求
代码如下(示例):规定在一个集合中,添加自定义Person类类型的数据,对Person类进行封装,并要求用getXXX返回其值,用传统方法实现代码如下:
(1)Person类的定义及main函数
class Person {//Person 类
private String name;//对属性进行封装
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new Person("张一凡",20));
arrayList.add(new Person("刘一鸣",18));
for (int i = 0; i < arrayList.size(); i++) {
Person person = (Person)arrayList.get(i);//.get 返回Object,向下转型
System.out.println(person.getAge()+"***" +
person.getName());
}
}
分析)
1. 我们可以看到对每一次的遍历,都要 向下转型 必定耗费资源,较低效率。
2. 同样如果我们不小心向集合中加入了不是 Person类的数据,编译不会出错,运行会出java.lang.ClassCastException,程序的健壮性较差。
2.泛型入门
对上面一个问题 我们可以使用泛型,对集合中的数据类型进行限制,如果数据添加不符合,编译出错,容易检查,且不用向下转型就可使用getXX。
对上个问题改进-----使用泛型》代码如下:
public static void main(String[] args) {
ArrayList<Person> arrayList = new ArrayList<>();//这两种方式都可以,推荐第一种
//,更简洁
//ArrayList<Person> arrayList = new ArrayList<Person>();
arrayList.add(new Person("张一凡",20));
arrayList.add(new Person("刘一鸣",18));
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i).getName()+
arrayList.get(i).getAge());
}
}
3.泛型在集合中的好处
1. 增强代码健壮性
2. 对某种特定的需求,可以提高效率。
3. 对集合中数据的类型进行限制。
三、自定义泛型
1. 自定义泛型类
(1)语法
class 类名 <E> {//<>中的字母 自定义
}
(2)泛型属性
(1)可以在类成员(非静态成员)进行修饰,在创建这个对象时,类型就是确定
public class Generic02 {
public static void main(String[] args) {
new Animal<String,Double>("老虎",6.0).show();//Double 是 double 的封装类
}
}
class Animal<E,F> {// 申明了两个泛型,完成对象的创建会确定其类型
private E name;
private F age;
public void show () {
System.out.println( "参数name的类型是" +
name.getClass().getSimpleName()+
"\t" + "参数age的类型是" +
age.getClass().getSimpleName() );
}
参数name的类型是String 参数age的类型是Double
(2)不能在静态属性使用泛型。原因:在创建对象之前,虚拟机 会在方法区先完成类加载,加载的同时,不能解析该属性的类型,故编译出错。
cannot be referenced from a static context
(3)泛型方法
(1)语法
访问修饰符 <E,F> 返回类型 函数名称 (E e,F f ) {//<>中 字母可自定义
}
注意:如果没有<> 就不是泛型方法,而是方法使用了泛型。
访问修饰符 返回类型 函数名称 (E e,F f ) {//<>中 字母可自定义
}
(2)如果静态方法使用泛型,则必须声明为泛型方法,否则会编译出错
public static <E> void show(E e) {
}
cannot be referenced from a static contex
(2)使用规则
1 .调用该函数,传入参数时,会自动辨别类型
public static void main(String[] args) {
show("你好",15);
}
public static <E,F> void show (E e,F f ) {
System.out.println(e.getClass()+" "+f.getClass());
}
class java.lang.String class java.lang.Integer
2. 泛型在方法中的好处
(1) 可以接受任何参数,对这些参数进行类型辨析,然后对其处理。
二、泛型接口
1. 基本语法
interface A <e,t,,,> {//<>z中的字母和数量自定义 }
2. 细节
1. (成员变量 只能是常量。默认修饰符 public static final)静态成员不能使用泛型。
2. 在实现接口或者继承接口时,类型确定。
3 . 如果没有指定,默认Object。
interface textone <K,V > {
void show (K k,V v);
}
interface A extends textone <String,Integer>
//接口继承声明了泛型的类型
{
}
class fast implements A {//类实现A接口,抽象方法中的类型就会匹配
//接口A申明的类型
@Override
public void show(String s, Integer integer) {
}
}
3、泛型继承
1. 泛型不具备继承
即左右<>不能不同,列如 List<Object> list = new ArrayList<String>();//编译出错。
四、通配符
(1)<?> 支持任意泛型类型
public static void main(String[] args) throws Exception {
ArrayList<Integer> integerArrayList = new ArrayList<>();
ArrayList<String> stringArrayList = new ArrayList<>();
printList(integerArrayList);
printList(stringArrayList);
}
public static void printList (Collection<Object> list) {
for (Object obj: list) {
System.out.println(obj);
}
}
因为泛型不具有继承性 所以会编译出错
(改进:要用<?> 无边界通配符)
public static void main(String[] args) throws Exception {
ArrayList<Integer> integerArrayList = new ArrayList<>();
ArrayList<String> stringArrayList = new ArrayList<>();
printList(integerArrayList);
printList(stringArrayList);
}
public static void printList (Collection<?> list) {
for (Object obj: list) {
System.out.println(obj);
}
}
我们要注意 在 printList 方法中,不是使用 关于参数的函数,例如 list.add();,可以使用无光参数的比如 :list.size()。
3.< ? extends A > 支持 A 即 A的子类,规定泛型的上限。
List < ? extends 类型1> list = new ArrayList<类型2>();
注解 类型2只能是类型1或者类型1的子类
public static void main(String[] args) throws Exception {
List< ? extends Number> list = new ArrayList<Integer>();
List< ? extends Number> list2 = new ArrayList<String>();
//list2 错误,因为String 不是 Number 的子类
}
4. < ? super A > 支持 A 即 A 的父类,规定了泛型的下限
List < ? super 类型1> list = new ArrayList<类型2>();
注解 类型2只能是类型1或者类型1的父类,不局限于直接父类
List<? super Floa> x = new ArrayList<Number>();//这是正确的
List<? super Integer> x = new ArrayList<Double>();//这是错误的
(5)总结
对对象的权限
1.只读--------> extends 关键字 规定上限
2.只写---------> super 关键字,规定下限
五、结束语
对泛型及通配符的基础和我的浅微理解就总结到这了,欢迎大家观看,批评。