泛型

泛型

Java集合有一个缺点就是把一个对象”丢进去“之后。集合就会”忘记“这个对象的数据类型,当再次取出该对象时,该对象的变异类型就会变成Object类型(运行时类型不变)。
这样设计的原因就是为了提高集合的通用性,但是会带来下面两个问题:
1.集合元素类型无限制,可能引起异常,不同的对象都可以放入集合,就会以引起异常。
2.由于集合对象放入集合时,集合对象就会丢失对象的状态信息,集合只知道它盛装的是Object,因此取出集合元素后通常还需要进行强制类型转换。不仅提高编程复杂度,而且可能引起ClassCastException。

import java.util.ArrayList;
import java.util.List;

public class ListErr {
    public static void main(String[] args) {
        //创建一个只保存字符串的List集合
        List strList = new ArrayList();
        strList.add("Home");
        strList.add("School");
        //向集合中加入一个Integer类型
        strList.add(12);
        //遍历集合
        for (Object str  : strList){
            System.out.println((String)str);
        }
    }
}

这样就会出现一个ClassCastException异常
如果使用泛型的话就不会出现上述异常,如果你非要向集合中加入一个Integer类型时就会直接编译报错,修改代码如下

import java.util.ArrayList;
import java.util.List;

public class ListErr {
    public static void main(String[] args) {
        //创建一个只保存字符串的List集合
        List<String> strList = new ArrayList<>();
        strList.add("Home");
        strList.add("School");
        //向集合中加入一个Integer类型
        //strList.add(12);//编译报错
       for (String str  : strList){
            System.out.println(str);
        }
    }
}

泛型语法

泛型的语法如下
在Java7以前,如果使用带泛型的接口、类的定义的变量,那么构造器创建对象时构造器后必须要加泛型,这就显得有点多余了,所以在Java7以后构造器后的泛型可以省略。

List<String> strList = new ArrayList<>();

泛型接口、类

泛型类
当一个类要操作的引用数据类型不确定的时候,可以给该类定义一个形参。用到这个类的时候,通过传递类型参数的形式,来确定要操作的具体的对象类型。在JDK1.5之前,为了提高代码的通用性,通常把类型定义为所有类的父类型:Object,这样做有两大弊端:

  1. 在具体操作的时候要进行强制类型转换;
  2. 这样还是指定了类型,还是不灵活,对具体类型的方法未知且不安全。
    如下:
public class MyClass {
    private Object obj;

    public Object getObj() {
        return obj;
    }

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

但是如果我们用泛型来定义的话就不会有这些问题

public class MyClass2<M> {
    private M m;
    public M getM() {
        return m;
    }
    public void setM(M m) {
        this.m = m;
    }
}

泛型接口
将泛型原理用于接口实现中,就是泛型接口。
泛型接口的格式:泛型接口格式类似于泛型类的格式,接口中的方法的格式类似于泛型方法的格式。
定义一个泛型接口

public interface MyInterface <T>{
    public T read(T t);
}

使用这个泛型接口

public class Test4 implements MyInterface<String>{

    public static void main(String[] args) {
        Test4 t = new Test4();
        System.out.println(t.read("Hello interdace"));
    }

    @Override
    public String read(String str) {
        return str;
    }

}

泛型方法

泛型方法也是为了提高代码的重用性和程序安全性。编程原则:尽量设计泛型方法解决问题,如果设计泛型方法可以取代泛型整个类,应该采用泛型方法。
泛型方法的格式:类型变量放在修饰符后面和返回类型前面, 如:public static E getMax(T… in)

public class Max {
    public static void main(String[] args) {
        System.out.println(getMax(1,2));
        System.out.println(getMax(0.3,0.5));
    }
    public static<T> T getMax(T t1,T t2){
        return t1.equals(t2)? t1: t2;
    }
}

泛型通配符

当操作的不同容器中的类型都不确定的时候,而且使用的元素都是从Object类中继承的方法,这时泛型就用通配符“?”来表示。
泛型的通配符:“?” 相当于 “? extends Object”

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class AllCollectionIterator {

    public static void main(String[] args) {
        HashSet<String> s1 = new HashSet<String>();
        s1.add("sss1");
        s1.add("sss2");
        s1.add("sss3");
        ArrayList<Integer> a1 = new ArrayList<Integer>();
        a1.add(1);
        a1.add(2);
        a1.add(3);
        a1.add(4);

        printAllCollection(a1);
        System.out.println("-------------");
        printAllCollection(s1);
    }

    public static void printAllCollection(Collection<?> c){
        Iterator<?> iter = c.iterator();
        while (iter.hasNext()) {
            System.out.println(iter.next().toString());

        }
    }

}

泛型限定
泛型限定就是对操作的数据类型限定在一个范围之内。限定分为上限和下限。
向上限定:? extends E 接收E类型或E的子类型
向下限定:? super E 接收E类型或E的父类型
限定用法和泛型方法,泛型类用法一样,在“<>”中表达即可。
一个类型变量或通配符可以有多个限定,多个限定用“&”分隔开,且限定中最多有一个类,可以有多个接口;如果有类限定,类限定必须放在限定列表的最前面。如:T extends MyClass1 & MyInterface1 & MyInterface2

import java.util.Calendar;
import java.util.GregorianCalendar;
 
public class GenericGetMax {
 
	public static void main(String[] args) {
		String[] inArrStr = {"haha", "test", "nba", "basketball"};
		System.out.println(GetMax.findMax(inArrStr).toString());
		Integer[] inArrInt = {11, 33, 2, 100, 101};
		System.out.println(GetMax.findMax(inArrInt));
		GregorianCalendar[] inArrCal = {
				new GregorianCalendar(2016, Calendar.SEPTEMBER, 22),
				new GregorianCalendar(2016, Calendar.OCTOBER, 10)};
		System.out.println(GetMax.findMax(inArrCal).toZonedDateTime());
	}
}
 
class GetMax {
	@SafeVarargs
	public static <T extends Comparable> T findMax(T... in) {
		T max = in[0];
		for (T one : in) {
			if (one.compareTo(max) > 0) {
				max = one;
			}
		}
		return max;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值