泛型类,泛型方法,泛型接口以及泛型扩展

一.泛型深入:

集合的泛型如果用基本数据类型的话要用包装类,如int要用Integer


二.介绍没有泛型的时候,集合如何存储数据:

下拉框的第一个提示的Object e代表可以添加任意类型的数据


javabean类:

package com.itheima.a04mygenerics;
​
class Student {
    private String name;
    private int age;
​
    //构造
    public Student() {
    }
​
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
​
    //set/get
    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 String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
 

测试类里:

package com.itheima.a04mygenerics;
​
import java.util.ArrayList;
import java.util.Iterator;
​
public class GenericsDemo1 {
    public static void main(String[] args) {
        //1.创建集合的对象
        ArrayList list=new ArrayList<>();
​
        //2.添加数据
        list.add(123);
        list.add("aaa");
        list.add(new Student("zhangsan",123));
​
        //3.遍历集合获取里面的每一个元素
        Iterator it = list.iterator();
        while (it.hasNext()){
            Object obj=it.next();//此时没有泛型,所有元素都提升为Object型
            System.out.println(obj);
        }
        /*运行结果为123
                  aaa
                  Student{name = zhangsan, age = 123}
                  */
​
    }
}
​

结论:

package com.itheima.a04mygenerics;
​
import java.util.ArrayList;
import java.util.Iterator;
​
public class GenericsDemo1 {
    public static void main(String[] args) {
        /* 结论:
           如果没有给集合指定类型,默认所有的数据类型都是Object类型
           此时可以往集合添加任意类型的数据
           弊端:在获取数据的时候-->无法使用他的特有行为
           
           因此有了泛型,可以在添加数据的时候就把数据类型进行统一。
           在获取数据的时候也无需强制转换了
        
         */
        
        
        //1.创建集合的对象
        ArrayList list=new ArrayList<>();
​
        //2.添加数据
        list.add(123);
        list.add("aaa");
        list.add(new Student("zhangsan",123));
​
        //3.遍历集合获取里面的每一个元素
        Iterator it = list.iterator();
        while (it.hasNext()){
            Object obj=it.next();//此时没有泛型,所有元素都提升为Object型
            /* Object型为基(最大父)类,但多态有一个弊端,即
               不能访问子类特有的功能
                所有obj不能调用整型,字符串型,Student型的特有功能
                而且还不能强制转换类型
                比如强制转换为Student型,123和"aaa"就不行了
            
             */
            
            
            System.out.println(obj);
        }
        /*运行结果为123
                  aaa
                  Student{name = zhangsan, age = 123}
                  */
​
    }
}
​

三.泛型的好处:


四.扩展:

当集合指定泛型后,如添加一个数据并添加成功-->在集合里还是会默认升为Object型-->当出集合会强制转换回来初始类型


代码的体现:

当编写Java文件时,Java文件里真正存在泛型-->当Java文件编写为.class即字节码文件后泛型会消失(泛型的擦除)


五.泛型的细节:

1.泛型中不能写基本数据类型:

因为基本数据类型不能转为Object型-->因此要把基本数据类型转换为包装类才行

2.指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型;

3.如果不写泛型,类型默认是Object。


六.泛型类:

实例:

package com.itheima.a04mygenerics;
​
import java.util.Arrays;
​
/*
   在编写一个类时,如果不确定类型,那么这个类就可以定义为泛型类
   本例中E是用来记录数据类型的,比如E可以是String型,Integer型等
​
 */
public class MyArrayList<E> { //E代表定义了一个不确定的类型,之后就可以用这个类型
    //左侧边框类显示的还是MyArrayList,这个没啥影响
​
    //ArrayList源码底层是Object型的数组,因此定义一个数组
    Object[] obj=new Object[10];
​
    //定义一个变量用来记录存了几个元素
    //size为全局变量,初始值默认为0
    int size;
​
    public MyArrayList() {
    }
​
    public MyArrayList(Object[] obj, int size) {
        this.obj = obj;
        this.size = size;
    }
​
    //定义一个方法,用来添加元素
    //由于不知道存入的数据的类型,因此把形参定义为和类一样的泛型
    //E是不确定的数据类型,该类型在类名后面就已经定义过了;e为变量名(形参的名字)
    public boolean add(E e){
        //把元素添加到obj数组中
        obj[size]=e;//第一次时size为0(因为size为全局变量,第一次默认为0)
        size++;
​
        //return true表示添加成功
        return true;
    }
​
​
    //定义一个方法,用来获取元素
    //返回值类型不是Object型,而是这个不确定的类型E
    public E get(int index){
        //返回数组obj中index索引上的元素
        //不是return obj[index];-->因为此时返回值类型为Object,而返回值类型为E,因此要强制转换类型
        return (E) obj[index];
    }
​
​
​
    //重写顶级父类Object的toString方法,为了打印属性,而不是地址值
    public String toString() {
        //return Arrays.toString(obj);代表把数组里的元素拼接为字符串并返回
        return Arrays.toString(obj);
    }
​
}
​

实现类1:

package com.itheima.a04mygenerics;
​
public class GenericsDemo2 {
    public static void main(String[] args) {
        //注:如果类名后带有泛型,那么创建对象时就必须传递类型
        MyArrayList<String> list=new MyArrayList<>();
        //此时类MyArrayList<E>里的E就记录的String型
​
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
​
        System.out.println(list);
        /*运行结果为[aaa, bbb, ccc, null, null, null, null, null, null, null]
            类MyArrayList里的数组长度为10,本例只添加了三个元素,剩下的用默认值null
        */
​
    }
}
​

实现类2:

package com.itheima.a04mygenerics;
​
public class GenericsDemo2 {
    public static void main(String[] args) {
        MyArrayList<Integer> list=new MyArrayList<>();
​
        list.add(123);
        list.add(456);
        list.add(789);
​
        int i = list.get(0);
        /* Integer i = list.get(0);和
           int i = list.get(0);都行,因为Java中有自动装箱和自动拆箱的功能
         */
​
        System.out.println(i);//运行结果为123
        System.out.println(list);//运行结果为[123, 456, 789, null, null, null, null, null, null, null]
​
    }
}

注:本例中一定要指定泛型E的类型,不然就默认为Object型。


七.泛型方法:

1.当方法形参类型不确定时:

解决方案1:使用类名后面定义的泛型-->所有方法都能用

如果所有方法数据类型都不确定,建议用泛型类

解决方案2:在方法申明上定义自己的泛型-->只有本方法能用

如果只是某个方法中出现了不确定的数据类型,建议用泛型方法

2.泛型方法定义格式:

3.实例:

题目:


解:
工具类:
package com.itheima.a04mygenerics;
​
import java.util.ArrayList;
​
public class ListUtil {
    //对于工具类最好私有化构造方法,不让外界创建它的对象
    public ListUtil(){}
​
​
      /*形参需要要添加的集合的元素,因此还需要集合*/
      //addAll方法-->添加的元素的类型不确定,因此可以定义为泛型方法,也可以定义为泛型类
    public static<E> void addAll(ArrayList<E> list,E e1,E e2,E e3,E e4){ //也可写为public static <E>void addAll
       //public和static均为修饰符
        list.add(e1);
        list.add(e2);
        list.add(e3);
        list.add(e4);
    }
}
测试类:
package com.itheima.a04mygenerics;
​
import java.util.ArrayList;
​
public class GenericsDemo3 {
    public static void main(String[] args) {
​
        ArrayList<String> list=new ArrayList<>();
        //指定了泛型为String型,因此list只能操作String型
​
        ListUtil.addAll(list,"aaa","bbb","ccc","ddd");
​
        System.out.println(list);//运行结果为[aaa, bbb, ccc, ddd]
    }
}

工具类优化-->可以添加任意个元素:
package com.itheima.a04mygenerics;
​
import java.util.ArrayList;
​
public class ListUtil {
    //对于工具类最好私有化构造方法,不让外界创建它的对象
    public ListUtil(){}
​
​
      /*形参需要要添加的集合的元素,因此还需要集合*/
      //addAll方法-->添加的元素的类型不确定,因此可以定义为泛型方法,也可以定义为泛型类
    public static<E> void addAll(ArrayList<E> list,E e1,E e2,E e3,E e4){ //也可写为public static <E>void addAll
       //public和static均为修饰符
        list.add(e1);
        list.add(e2);
        list.add(e3);
        list.add(e4);
    }
​
    public static<E> void addAll2(ArrayList<E> list,E...e){ //可以添加任意个元素
        //E...e(有三个.)-->叫可变参数,底层是数组
        for (E element : e) {
            list.add(element);
        }
    }
}
​
测试类:
package com.itheima.a04mygenerics;
​
import java.util.ArrayList;
​
public class GenericsDemo3 {
    public static void main(String[] args) {
​
        ArrayList<String> list=new ArrayList<>();
        //指定了泛型为String型,因此list只能操作String型
​
        ListUtil.addAll2(list,"aaa","bbb","ccc","ddd","eee","a","b");
​
        System.out.println(list);//运行结果为[aaa, bbb, ccc, ddd, eee, a, b]
    }
}


八.泛型接口:

当接口中数据类型不确定时,可以定义为泛型接口。


第一种使用方式:实现类给出具体数据类型(该实现类不是接口)-->实现类确定类型时用

实现类:
package com.itheima.a04mygenerics;
​
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
​
public class MyArrayList2 implements List<String> {
    //List<String>代表集合中只能存String型数据-->因此重写的add方法只能操作String型
    //List中有很多方法需要重写,可以根据报错提示进行快速改正
​
​
    @Override
    public boolean add(String s) {
        return false;
    }
​
    @Override
    public int size() {
        return 0;
    }
​
    @Override
    public boolean isEmpty() {
        return false;
    }
​
    @Override
    public boolean contains(Object o) {
        return false;
    }
​
    @Override
    public Iterator<String> iterator() {
        return null;
    }
​
    @Override
    public Object[] toArray() {
        return new Object[0];
    }
​
    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }
​
    @Override
    public boolean remove(Object o) {
        return false;
    }
​
    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }
​
    @Override
    public boolean addAll(Collection<? extends String> c) {
        return false;
    }
​
    @Override
    public boolean addAll(int index, Collection<? extends String> c) {
        return false;
    }
​
    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }
​
    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }
​
    @Override
    public void clear() {
​
    }
​
    @Override
    public String get(int index) {
        return null;
    }
​
    @Override
    public String set(int index, String element) {
        return null;
    }
​
    @Override
    public void add(int index, String element) {
​
    }
​
    @Override
    public String remove(int index) {
        return null;
    }
​
    @Override
    public int indexOf(Object o) {
        return 0;
    }
​
    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }
​
    @Override
    public ListIterator<String> listIterator() {
        return null;
    }
​
    @Override
    public ListIterator<String> listIterator(int index) {
        return null;
    }
​
    @Override
    public List<String> subList(int fromIndex, int toIndex) {
        return null;
    }
​
}
测试类:
package com.itheima.a04mygenerics;
​
public class GenericsDemo4 {
    public static void main(String[] args) {
        //泛型接口的第一种使用方式:实现类给出具体的类型
         //创建对象时不用写泛型,因为接口中后面没指定,而且存储的数据类型也已经固定了
        MyArrayList2 list1=new MyArrayList2();
        list1.add("abc");
        System.out.println(list1);
    }
}

第二种使用方式:实现类延续泛型,创建实现类对象后再确定类型-->实现类不确定类型时用

实现类:
package com.itheima.a04mygenerics;
​
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
​
public class MyArrayList3<E> implements List<E>{ //List<E>,不是List<E e>
    //泛型类带有泛型接口
​
    //比如add方法,形参类型就是不确定的数据类型
    @Override
    public boolean add(E e) {
        return false;
    }
​
    @Override
    public int size() {
        return 0;
    }
​
    @Override
    public boolean isEmpty() {
        return false;
    }
​
    @Override
    public boolean contains(Object o) {
        return false;
    }
​
    @Override
    public Iterator<E> iterator() {
        return null;
    }
​
    @Override
    public Object[] toArray() {
        return new Object[0];
    }
​
    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }
​
    @Override
    public boolean remove(Object o) {
        return false;
    }
​
    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }
​
    @Override
    public boolean addAll(Collection<? extends E> c) {
        return false;
    }
​
    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return false;
    }
​
    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }
​
    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }
​
    @Override
    public void clear() {
​
    }
​
    @Override
    public E get(int index) {
        return null;
    }
​
    @Override
    public E set(int index, E element) {
        return null;
    }
​
    @Override
    public void add(int index, E element) {
​
    }
​
    @Override
    public E remove(int index) {
        return null;
    }
​
    @Override
    public int indexOf(Object o) {
        return 0;
    }
​
    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }
​
    @Override
    public ListIterator<E> listIterator() {
        return null;
    }
​
    @Override
    public ListIterator<E> listIterator(int index) {
        return null;
    }
​
    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return null;
    }
​
}
​
测试类:
package com.itheima.a04mygenerics;
​
public class GenericsDemo4 {
    public static void main(String[] args) {
        //泛型接口的第二种使用方式:实现类延续泛型,创建实现类对象后再确定类型
         //创建对象时必须要给出数据类型,因为接口中是不确定数据类型
        MyArrayList3<String> list=new MyArrayList3<>();
        list.add("aaa");
        System.out.println(list);
​
    }
}
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值