1.泛型的简单介绍和使用
- 泛型是JDK1.5之后增加的,可以用来建立类型安全的集合;
- 什么是类型安全的集合?就我看来,就是说只能使用某一个指定了的类,而不能使用其他类的对象;
- 在使用自定义的泛型时,也就是在类中声明时,一般使用<T,E,V>。当然也可以用其他的字母来表示,但是最好还是用这些常用的字母;
- 泛型的<>中存放的是包装类,所谓的包装类,就是将基本类型进行装箱后的一种Java类;比如像是Integer,Short,等总计8个;我前面博客有介绍;
public class TextGeneric {
public static void main(String[] args) {
Animal<String> ani= new Animal<String>();//在这里面定义该类中规定的类型为String
Animal<String> ani1 = new Animal<String>();//那么这些对象中后面所有方法引入的也必须是这个String类型;
ani.setName("dog");
ani1.setName("cat");
// ani.setName(123);//如果定义的类型与前面的String不同就无法写入;会报错;
System.out.println(ani1.getName());
}
}
class Animal<E>{//定义一个带泛型的类,当然如果想多带一个参数类型,只需要在后面再添一个,如Animal<E,V>;
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
public Animal() {
}
}
这个基本就是泛型的使用方法;
2.了解基础的通配符
首先通配符的使用是在了解泛型的基础上,能熟练使用通配符,不说多的,至少代码的简洁性一定有,至于其它相关的东西,边学边记录吧;
public class TestTo {
public static void main(String[] args) {
// 首先定义两个ArrayList的对象;
List<String> list = new ArrayList<>();
List<Object> list1 = new ArrayList<>();
// 分别给两个对象添加一些东西;
list.add("string");
list.add("神");
list1.add("神秘的天");
list1.add("sdd");
//通过调用下方使用了通配器的方法;迭代输出list和list1中的值
new TestTo().show(list1);
new TestTo().show(list);
}
//在这里就可以使用通配符,
public void show(List<?> list) {
// 当然是用for循环更简单,但是使用一下迭代器输出,就当回顾之前的知识吧;
Iterator<?> iterator = list.iterator();
while(iterator.hasNext()){
Object o = iterator.next();
System.out.println(o);
}
/* for (Object o : list) {
System.out.println(o);
}*/
}
}
运行结果:
如上例在通配符中,List<?>这个其实属于List<Object>和List<String>的一种父类吧,所以就像是利用了多态一样;这样就不需要重载几个方法了;我这里只是通过方法显示了通配符的用处,其实按道理,有很多的地方都可以用到通配符;而且为什么不直接使用List<Object>代替List<?>,那是因为,List<String>其实并不继承List<Object>;
最后需要注意的是,如下图:如果定义了一个这样的list,那么list后面不能添加其它的数据;比如;
List<?> list;
//list.add("dd");这是错误的写法;最多就只能把list置空;
//比如下面:
list=null;
2.1有限制条件的通配符
有限制条件的通配符主要是指就像是给大小进行判断一样,比如前面只有<?>的时候,可以看做是没有范围,什么泛型都可以是它的子类;但是当如下时<? extends TestClose>的子类泛型就必须是TestClose的子类;怎么了解呢,我们通过多态的赋值进行解释;如下程序;
public class TestClose {
public void test() {
//这里定义一下这两种类型的通配符;
List<? super TestClose> list1 = null;//看意思大致是TestClose的父类;
List<? extends TestClose> list2 = null;//这里可能是继承自TestClose的子类;
List<Test> list3 = null;//定义比较类;
List<TestClose> list4 = null;
List<Object> list5 = null;
//通过赋值就可以知道这些通配符的含义;
//list1=list3;只有这个赋值给list1的时候报错,由此证明list1只能接受比他TestClose大的父类或等于它;
list1 = list4;
list1 = list5;
list2 = list3;
list2 = list4;
//list2=list5;这个赋值的时候报错,也由此知道list2只能接受TestClose的子类或者它本身的泛型;
}
}
class Test extends TestClose {
}
以下程序主要稍微详细的理解一下限制性的通配符:
public static void main(String[] args) {
List<? super Person> list1 = new ArrayList();
list1.add(new Person("dss"));//可以插入
Object l = list1.get(0);//可以取值,但不能确定值的类型;只能用最大的object修饰;
System.out.println(l.toString());
List<? extends Person> list =new ArrayList<>();
// list.add(new Person());这是错的,但其实在我之前的理解,我一直以为它是对的;为什么错误,下面解释;
Person p = list.get(0);//相较于上面取值的广泛,在这里取值的时候范围更加明确;
List<Person> list3;
}
首先就是在<? extends A>中,可以这样看,那个?的大致范围是要继承A类的;那么在List的容器中,就只有比它小的类的对象才能放进去;但是这个很小的类是不明确的,所以使用add方法添加值的时候,就只能添加null,否则程序本身就会报错;
为了让自己下次复习的时候看不懂,我还是简单的再讲讲自己的想法;
首先List<? extends A>,我们假设B继承A,那么?就可以用B来代替是吧,然后就是在容器中,使用add方法时;你所添加的按照多态来说你,你最大的类都不过是A,而且极有可能取到的类是A的子类,那么如果我们按最大的来添加,也最多list.add(new A());何况我们根本无法确定它的准确取值,这样我们是无法add的,这就是为什么上面的添加会报错的终极原因;