集合(8):泛型类、泛型方法、泛型接口


集合(8):泛型类、泛型方法、泛型接口

前言案例

import java.util.ArrayList;
import java.util.Iterator;

public class GenericDemo1 {
    public static void main(String[] args) {
        //创建List集合对象
        ArrayList list = new ArrayList();
        //向集合中添加元素
        list.add("hello");
        list.add(10);//相当于向上转型,10 -- int -- Integer
        list.add("world");
        //获取迭代器对象
        Iterator iterator = list.iterator();
        //获取迭代器对象
        while(iterator.hasNext()){
            Object next = iterator.next();
            String s = (String)next;
            System.out.println(s);
        }
    }
}

执行结果如下:

image

我们按照正常的写法,在集合中添加一些不是同类型的数据,在遍历的时候向下转型报错了
ClassCastException:类型转换异常
为什么呢?
    因为我们在存储数据的时候,存储了一些String和Integer类型的数据,但是呢,
    我们遍历的时候,默认集合中只存放String类型的数据;但是在存储数据的时候
    没有告诉我们只能存String类型的数据,如果能在存储的时候告诉我能存储哪些数据类型就好了
    String[] arr = new String[3];//创建数组的时候明确的元素的类型
          arr[0] = "hello";
       // arr[1] = 20;当添加int类型的时候是不可行的

java中集合就模仿着数组呢,也有这样的做法,在创建集合的时候,就明确了元素的数据类型,
创建后,再往集合中加入的元素,只能是定义好的数据类型相关的数据了,然后再向下转型就没有问题了。
这样的技术,java中叫做:泛型

泛型

一、泛型的使用介绍

1、泛型的概述
把明确数据类型的工作,提前到了编译时期,在创建集合的时候明确数据类型,
这样的做法有点像把数据类型当作参数一样进行传递。
所以泛型还有一个名字叫做:参数化类型
2、泛型的定义格式
定义格式:
     <引用数据类型>,在API中是<E>
     注意:尖括号中的数据类型只能是引用数据类型,<E>在创建对象的时候添加在类后面

格式案例:

ArrayList<String> list = new ArrayList<String>();

JDK1.7之后会自动进行类型推断
所以后面的<String>中的String可加可不加,建议加上
当创建对象的时候加入了泛型,迭代器也要加上泛型
//获取迭代器对象
Iterator<String> iterator = list.iterator();
在没使用泛型的时候,添加不同类型元素的时候,不会报错,在向下转型的时候才会报错;
当使用泛型的时候,在添加元素的时候,编写代码的时候就会报错,提前报错,便于我们更改
3、泛型的好处
添加泛型之后
(1)将我们之前运行时候出现的问题,提前到了编译时期
(2)不需要强制类型转换了,而且还可以调用元素类型的方法
(3)优化了代码,消除不必要的黄色警告线
4、泛型的使用场景
通过观察API发现,泛型可以出现了类,接口,方法上,看到一些类似与<E>,
一般来说泛型出现在大多使用集合中

二、泛型的应用

1、泛型类
泛型类:把泛型定义在类上(在类名后面添加<变量名>)
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
这里的<>里面的内容仅仅表示的是一种参数数据类型,参数类型是一种变量,
既然是一种变量,就符合变量的命名规则,可以是任意符合标识符起名规则的名字

泛型类的使用

//第1步:定义一个泛型类
class GenericTool1<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

//第2步:泛型类的测试
public class GenericTest1 {
    public static void main(String[] args) {
    /*
    	如果前面定义的类不加泛型,默认则是Object类型
		GenericTool1 gt1 = new GenericTool1();
		添加元素的时候,类型可以是任意的
		gt1.setObj("hello");
		gt1.setObj(20);
		gt1.setObj(12.34);
		gt1.setObj(new Student());
    */
		//创建泛型类的对象
        GenericTool1<String> gt = new GenericTool1<>();
        //调用setObj()方法添加元素
        gt.setObj("hello");
		//gt2.setObj(20);定义过泛型之后,就不能再添加不同类型的元素
		
        //调用getObj()方法获取元素
        String obj = gt.getObj();
        System.out.println(obj);
    }
}
            执行结果如下:
                        hello

                        Process finished with exit code 0
2、泛型方法
泛型方法:把泛型定义在方法上

格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
    例:
	public<T> void show(T t){}

(1)在没使用泛型的时候,正常写个类来定义成员方法

//定义一个类
public class GenericTool2 {
    public void show(String s){
        System.out.println(s);
    }

    public void show(int i){
        System.out.println(i);
    }
    
     public void show(double d){
        System.out.println(d);
     }
}

//定义一个测试类
public class GenericTest2 {
    public static void main(String[] args) {
    //创建类的对象
	GenericTool2 gt1 = new GenericTool2();
    //调取类中的show方法,并赋值
	gt1.show(10);
	gt1.show("hello");
	gt1.show(12.34);
 	}
}
            执行结果如下:
                        10
                        hello
                        12.34

                        Process finished with exit code 0

当我们不使用泛型的时候,在测试类中赋值的时候,必须要根据定义的成员方法参数类型来赋值,

当需要赋值很多类型的时候,需要定义的成员方法也很多,非常的麻烦。

(2)当使用泛型类的时候,泛型类的成员方法参数类型和泛型类一致

赋值很多类型的时候,就不需要定义很多发成员方法了

//定义一个泛型类
class GenericTool2<T> {
    //定义成员方法,参数为T类型
    public void show(T t){
        System.out.println(t);
    }
}
//定义一个测试类
public class GenericTest2 {
    public static void main(String[] args) {
        GenericTool2 gt1 = new GenericTool2();
        //前面定义了泛型类,此处再赋值就可以随便赋值不同的类型了
        gt1.show(10);
        gt1.show("hello");
        gt1.show(12.34);
    }
}
     		执行结果如下:
                        10
                        hello
                        12.34

                        Process finished with exit code 0

(3)当定义了泛型类,泛型类的成员方法参数类型和泛型类一致,

如果在测试了中创建对象的时候也加上了泛型,会发生什么变化?

//定义一个泛型类
class GenericTool2<T> {
    //定义泛型成员方法
    public void show(T t){
        System.out.println(t);
    }
}
//定义一个测试类
public class GenericTest2 {
    public static void main(String[] args) {
        //创建泛型类对象的时候加上泛型
        GenericTool2<String> gt2 = new GenericTool2<>();
        gt2.show("hello");
        //gt2.show(20);当创建对象的时候加上了泛型,那么赋值int类型就会报错
        //想要赋值int类型的元素,就必须再创建一个int泛型的对象
        GenericTool2<Integer> gt3 = new GenericTool2<>();
        gt3.show(20);
    }
}
        执行结果如下:
                    hello
                    20

                    Process finished with exit code 0

由此可见,当定义了泛型类,泛型类的成员方法参数类型和泛型类一致,

在测试了中创建对象的时候也加上了泛型,

赋值不同类型的时候,需要创建很多的对象,就非常的麻烦

如果定义的类上面没有泛型的话,方法还能不能随便传参呢?

答案是可以的,不过这时候就需要用到泛型方法

而且测试类中创建对象的时候不能有泛型了,不然会报错

//定义一个类
public class GenericTool2 {
    //定义泛型成员方法
    public<T> void show(T t){
        System.out.println(t);
    }
}
//定义一个测试类
public class GenericTest2 {
    public static void main(String[] args) {
        //创建对象
        GenericTool2 gt = new GenericTool2();
        //定义泛型方法以后,赋值的时候,可以传入任意类型的参数
        gt.show("hello");
        gt.show(20);
        gt.show(true);
    }
}
        执行结果如下:
                    hello
                    20
                    true

                    Process finished with exit code 0
3、泛型接口
泛型接口:把泛型定义在接口上
格式:public interface 接口名<泛型类型1...>

案例:

//定义泛型接口,接口中的方法参数和接口一致
public interface GenericTool3<T> {
    public abstract void show(T t);
}
//定义一个类来实现泛型接口,实现接口的类也要加上泛型
public class GenericTool3Impl<T> implements GenericTool3<T>{
    //重写接口中的抽象方法
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}
//泛型接口的测试
public class GenericTest3 {
    public static void main(String[] args) {
        //接口不能实例化,需要new它的实现类
        GenericTool3Impl<String> sgt1 = new GenericTool3Impl<>();
        sgt1.show("hello");
    }
}

执行结果如下:

hello

Process finished with exit code 0


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM