我们为什么要使用泛型?
答:因为当我们将一个对象放入集合中时,集合不会记住此对象的类型,当再次从集合中取出此对象时,该对象的编译类型变成了Object类型,但其运行时类型依然是本身类型。
因此,当我们取出集合元素的时候就需要人为地强制转换类型,然后很容易就出现“java.lang.ClassCastException”异常,因为要避免类型转换异常,所以我们就需要使用泛型!
注:当我们使用泛型时,如果添加的值与泛型中的值不同时,那么就会编译错误!
泛型类
public class Generic {//定义泛型类
private T name;//泛型变量,但为了测试,提前写好了变量名
private T age;//泛型变量,但为了测试,提前写好了变量名
//Set和Get方法
public void setAge(T age) {
this.age = age;
}
public T getAge() {
return age;
}
public void setName(T name) {
this.name = name;
}
public T getName() {
return name;
}
}
调用泛型类
public class TestGeneric {
public static void main(String[] args){
//声明一个泛型为String类型的对象
Generic gg = new Generic();
gg.setName("路人甲");//调用set方法
//声明一个泛型为Integer类型的对象
Generic g = new Generic();
g.setAge(15);//调用set方法
//调用get方法
System.out.println(gg.getName() + "今年" + g.getAge() + "岁!");
}
}
泛型方法与泛型静态方法
//声明一个泛型类
public class GenericMethod {
//声明一个泛型普通方法
public void show(T t){
System.out.println(t);
}
//声明一个泛型静态方法
public static void StaticMethod(T t){
System.out.println("静态方法中的t:" + t);
}
}
调用泛型方法与泛型静态方法
public class TestGM {
public static void main(String[] args){
//声明一个String类型的泛型对象
GenericMethod g = new GenericMethod();
//调用普通的泛型方法
g.show("name1");
//调用静态的泛型方法
g.StaticMethod("name");
}
}
如何可以获取泛型中的类型
/*
*需要导入这两个包
* import java.lang.reflect.ParameterizedType;
* import java.lang.reflect.Type;
* */
abstract class Foo {
public Class getTClass() {
Class tClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
return tClass;
}
}
调用方法(不懂,先记下!)
Foo foo = new Foo() {};
// 在类的外部这样获取
Type type = ((ParameterizedType)foo.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(type);
// 在类的内部这样获取
System.out.println(foo.getTClass());
泛型接口
//声明一个泛型接口!
public interface GenericInterface {
//定义一个抽象方法,方法名为show,参数列表:类型为T,值为t
public abstract void show(T t);
}
类实现接口
//继承泛型接口
public class TestGI implements GenericInterface {
//重写方法
@Override
public void show(String s) {//规定了泛型为String类型
System.out.println("实现泛型接口中的方法:" + s);
}
}
调用接口中的方法
public class TestGI1 {
public static void main(String[] args){
//因为在实现类中已经定义了泛型,所以直接使用便是,定义类型为String类型
TestGI tgi = new TestGI();
tgi.show("路人甲!");
//下方的代码是要报错的,因为在泛型中已经规定了泛型为String类型
//TestGI tgi2 = new TestGI();
//tgi2.show(10);
}
}
接口,如果实现类不明确子类的参数类型时,也可以使用泛型来规定值!
//实现泛型接口,在类名后定义泛型
public class TestGI implements GenericInterface {
@Override
//因为不确定子类的参数类型,所以参数列表为泛型
public void show(T t) {
System.out.println("子类不明确泛型类的类型参数变量,实现类的时候也要定义出类型的:" + t);
}
}
实现泛型接口
TestGI tgi = new TestGI();
tgi.show(10);
通配符
?代表任意类型,使用通配符定义泛型类型,此时只能输出,不能修改!
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTPF {
public static void main(String[] args){
//定义一个Integer类型的集合
List list = new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
//调用静态方法,遍历list集合
test(list);
System.out.println();
//定义一个String类型的集合
List list1 = new ArrayList();
list1.add("路人甲");
list1.add("路人乙");
list1.add("路人丙");
list1.add("路人丁");
//调用静态方法,遍历list1集合
test(list1);
}
//写一个用来遍历集合的静态方法
public static void test(List> list){
//迭代器,需要加载java.util.Iterator;
Iterator> it = list.listIterator();
while(it.hasNext()){
Object o = it.next();
System.out.print(o + "\t");
}
}
}
泛型上限
只能调用本身及本身一下的类型,关键字为:<? extends 本身>,只能输出,不能修改!
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/* extends Number>
* ?相当于是子,Number相当于是父
* 只要是继承于Number的便可以
*/
public class GenericTPFE {
public static void main(String[] args){
/*
* 因为Integer是Number下面的子类,所以可以正常调用
* */
List list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
test(list);
/*
* Object远大于Number,所以会报错
* */
List
泛型下限
只能设置具体的类或者是父类,写法 super 类名或者父类>
import java.util.ArrayList;
import java.util.List;
public class GenericTPFS {
/*
* ? super 下限类
* 太阳为最高类,地球继承了太阳,月亮继承了地球
* */
static class Sun{}
static class Earth extends Sun{}
static class Moon extends Earth{}
public static void main(String[] args){
List list = new ArrayList();
test(list);//因为Earth继承了Sun,所以,满足Earth是下限的要求
List list1 = new ArrayList();
// test(list1);
/*
* 因为Moon继承了Earth,所以,不满足Earth是下限的要求
* */
}
public static void test(List super Earth> list){
System.out.println(list + "是权限高于Earth的类!");
}
}
好烦啊!!!!!本文为个人随笔,为方便日后自己查看所写,如有错误和不足的地方,请尽早联系!