JDK1.5之后出现了新的技术——泛型(Generic),此技术的最大特点是类中的属性的类型可以由外部决定。
而且在声明的时候应该采取如下的形式:
class类名称<泛型类型,泛型类型...>{
}
在使用泛型操作的时候,实际上有很多小的注意点,例如:构造方法上依然可以使用泛型或者有一种称为“泛型的擦除“。
相关术语:
ArrayList《E》:E称为类型变量或类型参数
ArrayList《Integer》:称为参数化类型
ArrayList《Integer》:其中Integer称为类型参数的实例或者实际参数类型
ArrayList《Integer》:<>称为type of
参数化类型与原始数据类型的兼容性
比如:
Collection<String>c=new Vector();
c.add("string");
或者可以为:
Collection c1=new Vector<String>();
c1.add("string");
但是注意一点就是,一个子类的对象可以指向一个超类的引用,这是java中的多态。
但是,参数化类型不存在继承关系
比如:
或者:
Collection<String> c2=new Vector<Object>();
都是错误的!!!
特别注意的就是定义数组不能使用泛型:
比如:
Person<String>[]ps=new Person<String>[];
这是错误的~
两个问题:
1、在构造方法上引用泛型
package com.demo.generic;
public class Person<T> {
/**
* 名字
*/
private String name;
/**
* 可能为1岁、一岁、1.5岁(int、string、float)
*/
private T age;
public Person(String name, T age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public T getAge() {
return age;
}
public void setAge(T age) {
this.age = age;
}
@Override
public String toString() {
return "我叫 :"+name+",我今年"+(age.toString())+"岁";
}
}
然后我们创建一个Person对象,在构造方法中指定参数类型:
public class Test {
public static void main(String[] args) {
Person<String> person =new Person("Yasin", "十八");
Person<Integer> person2 =new Person<Integer>("Yasin",18);
Person<Float> person3 =new Person<Float>("Yasin", 17.5f);
System.out.println(person);
System.out.println(person2);
System.out.println(person3);
}
}
2、如果在使用的时候没有指定泛型的话,则表示擦除泛型,泛型一旦擦除之后,将按照Object进行接收,以保证程序不出现任何的错误。
泛型的擦除为:
//泛型的擦除
Person person4=new Person("Yasin", 1);
通配符:
“?“表示的是可以接受任意的泛型类型,但是只是接收输出,不能进行修改。
什么意思呢?
比如我们需要打印person对象信息,于是我们定义一个方法:
public static void printInfo(Person<?> p,Object o){
p.setAge(age);//这里会报错,因为?声明的注解只能输出,不能修改
System.out.println(p.getAge());
}
泛型的上线(
public static void printInfo(Person <? extends Number>p,Object o){
p.setAge(1);
System.out.println(p.getAge());
}
这里的p只能传递Number类型或者其子类( Float、Integer…).
泛型的下限
例如:
public static void printInfo(Person <? super Number>p,Object o){
p.setAge(1);
System.out.println(p.getAge());
}
这里的p只能传递Number或者Number的父类…
使用泛型定义接口
如:
package com.demo.generic;
public interface Song<T>{
void name(T name);
}
class SongImp implements Song<String>{
@Override
public void name(String name) {
// TODO Auto-generated method stub
}
}
泛型方法
泛型除了定义在类中外,还可以定义在方法上,而且方法上使用泛型,此方法所在的类不一定是泛型的操作类。
例如(定义一个方法,实现任意类型数组两个位置的交换):
public static <T>T[] func(T[]array,int i,int j){
T temp=array[i];
array[i]=array[j];
array[j]=temp;
return array;
}
最后就是泛型的嵌套使用
最常见的就是我们的集合框架了:
List<Map<String,String>>datas=new ArrayList<Map<String,String>>();
好啦!!泛型内容就到此结束了额~~~