泛型在JAVA中有着十分重要的地位,泛型为JAVA程序提供了安全性,可扩展性,灵活性等特性
泛型
泛型:参数化类型,我们在对一个类,一个接口,一个方法,一个参数进行定义时,我们有时候不知道会存入类型的数据,我们有可能去接受各种各样的类型来完善我们的程序。
泛型的作用
在定义一个类的时候,类型有些方法参数,返回值类型不确定时,就是用一个符号,表示这些未确定的类型。
提高了安全性,在编译阶段就把类型转化的问题暴露出来,不会在运行中出现类型转换异常报错
不用再进行强转,强转会出现很多题需要解决处理
泛型的使用
泛型一般会在类的定义,接口的定义,方法的定义中去使用。而类和接口本质上是一样的东西,而方法都是在类中,所以对类进行泛型的使用就已经包括了所泛型使用的特点。接口是最抽象的,方法是最具体的,我们自顶向下进行分析
泛型修饰一个接口
用泛型修饰的接口成为泛型接口,因为接口是最抽象的,里面的所有方法需要实现类或者子类接口去实现或者继承,一旦接口中的泛型被确定了,关于这个泛型的所有下属体系不管是方法还是继承的类就都得到了确定。
我们从两个方面来进行分析,一是自定义的接口,还有就是从JAVA提供的接口中进行分析
来看代码
public class 接口练习 {
public static void main(String[] args) {
MyInter<String,Integer> m = new MyClass();
m.show("mmmmmmm");
m.show2(2222222);
m.show3("MMMMMMM",33333333);
}
}
interface MyInter<E,Q>{
E show(E e);
Q show2(Q q);
void show3(E e,Q q);
}
class MyClass<Y,M> implements MyInter<Y,M>{
Y yy;
M mm;
@Override
public Y show(Y y) {
System.out.println("我的类型为"+y.getClass());
return y;
}
@Override
public M show2(M m) {
System.out.println("我的类型为"+m.getClass());
return m;
}
@Override
public void show3(Y y, M m) {
System.out.println("Y的类型为"+y.getClass()+";M的类型为"+m.getClass());
}
}
输出结果
我的类型为class java.lang.String
我的类型为class java.lang.Integer
Y的类型为class java.lang.String;M的类型为class java.lang.Integer
我们从接口往下进行分析。在接口的定义中,我们定义了两个泛型(这里体现了泛型是可以设置多个泛型的特性),然后我们在泛型中的抽象方法中看到了这两个泛型进行定义的返回值和参数,接下来又定义了一个实现类,在实现类的定义上我们又看到了对接口的类型的继承,但是在这里用了和上面接口中完全不同的两个字母,这里其实是一样的,因为泛型本来就表示一个抽象的概念,一个不确定的东西用什么都能够进行表示,我们这里继承了接口,所以本质上是和接口一致的。然后我们又定义了一个实现类对上一个接口进行实现,在实现类中又继续继承了对接口父类泛型的继承,这里我们又可以用这里确定的泛型对这个实现类中的所有成员使用泛型,这里一层层的继承下来,就是为了去对这里真正能让对象使用的一些方法和属性进行定义,而这些都是我们进行的准备,所有的一切都是为了主方法中对对象的实例化,在实例化的一瞬间,这个对象所拥有的一切都有了定义,都有了具体的类型的使用。
泛型通配符
在我们使用集合或者其他方法定义的时候,我们可以在方法中进行一些定义,让这个方法可以接受一个系列的数据,比如Number类下的所有子类,但是非Number及其子类的类型不可以使用这个方法。
public static void main(String[] args) {
List<Number> list1 = new ArrayList<Number>();
List<Long> list2 = new ArrayList<Long>();
List<Integer> list3 = new ArrayList();
list1.add(13243);
f(list1);
f(list2);
f(list3); //编译错误
}
public static void f(List<? extends Number> list) {
System.out.println(list.get(0));//泛型通配符作为方法参数时只能够进行取值,不能够进行赋值,因为
Number number = list.get(0);
}
或者是在类的定义时设置一个泛型,然后成员方法中进行设置,可以对泛型进行不同定义的所有对象都能够互相调用
public class 泛型通配符 {
public static void main(String[] args) {
Person<Number> p = new Person();
Person<Integer> p1 = new Person();
p1.t = 1234;
p.show1(p1);
}
}
class Person<T>{
T t;
public void show1(Person<? extends T> p) {
System.out.println(p.t.getClass());
}
}