本文概要:
本节概要:
泛型的优点:
public class Location<T>{//标识符号可以随意写
private T x ;
private T y ;
public void setX(T x){//作为参数
this.x = x ;
}
public void setY(T y){
this.y = y ;
}
public T getX(){//作为返回值
return this.x ;
}
public T getY(){
return this.y ;
}
}
复制代码
以 , 进行分隔
public class MoreLocation<T,U> {//标识符号可以随意写
private T x;
private U y;
public void setX(T x) {//作为参数
this.x = x;
}
public void setY(U y) {
this.y = y;
}
public T getX() {//作为返回值
return this.x;
}
public U getY() {
return this.y;
}
}
复制代码
虽然标识符号可以随意取,但为了提高可读性,一般遵循以下规则.
在接口上定义泛型与在类中定义泛型是一样的
interface ILocation<T>{ // 在接口上定义泛型
T getZ() ;
void setZ(T z);
}
复制代码
public class LocationImpl implements ILocation<String>{
private String z ;
public LocationImpl(String z){
this.setZ(z) ;
}
@Override
public void setZ(String z){
this.z = z ;
}
@Override
public String getZ(){
return this.z ;
}
}
复制代码
publick class LocationImpl<T,K,U> implements ILocation<U>{ //把第三个泛型变量U用来填充接口
private U z ;
private T x;
private K y;
public LocationImpl(U z){
this.setZ(z) ;
}
@Override
public void setZ(U z){
this.z = z ;
}
@Override
public U getZ(){
return this.z ;
}
}
复制代码
在方法的返回值前加上来表示泛型变量.
public class MethodLocation {
public static <T> void staticMethod(T text) {
System.out.println("staticMethod:" + text);
}
//返回值与形参中存在泛型
public <T> T normalMethod(T text) {
System.out.println("normalMethod:" + text);
return text;
}
//定义泛型数组, T[]相当于String[].
public static <T> T[] funArray(T...arg){ // 接收可变参数
return arg ; // 返回泛型数组
}
public static void main(String[] args) {
MethodLocation methodLocation = new MethodLocation();
String text1 = methodLocation.normalMethod("hello");//方法1
String text2 = methodLocation.<String>normalMethod("genericity");//方法2
System.out.println("from main method:"+text1);
System.out.println("--------------------------");
Integer[] intArray = MethodLocation.funArray(1, 2, 3, 4, 5, 6);
System.out.println(Arrays.toString(intArray));
}
}
//输出结果
normalMethod:hello
normalMethod:genericity
from main method:hello
--------------------------
[1, 2, 3, 4, 5, 6]
复制代码
注意:虽然方法2是推荐方式,但实际在IDEA中会提示使用方法1,这是因为它会实时检测传入类型是否一致,不一致直接提醒编译不通过.
本节概要:
在前一节中,T只能是Object的子类,所以在编译时只能调用Object类的相关方法.假如现在有个dog类,我们想在编译时就调用他父类Animal的方法.这时就需要用到类型绑定.
定义:
< T extends BoundingType >
优点:
//省略....创建dog,Animal,IAction相关代码.
public class TypeBind {
public static void main(String[] args) {
Dog dog = new Dog("旺财");
String nameClass = getAnimalNameClass(dog);
System.out.println(nameClass);
System.out.println("---------------");
String actionInterface = getAnimalActionInterface(dog);
System.out.println(actionInterface);
System.out.println("---------------");
String nameAction = getAnimalNameAndAction(dog, dog);
System.out.println(nameAction);
}
//绑定类
private static <T extends Animal> String getAnimalNameClass(T sub) {
//这样编译时,就能调用Animal中的方法.
return sub.getName();
}
//绑定接口
private static <T extends IAction> String getAnimalActionInterface(T sub) {
return sub.howl();
}
//多个泛型绑定多个类型,通过&符号指定多个类型
private static <T extends Animal & Serializable, U extends IAction & Serializable> String
getAnimalNameAndAction(T sub1, U sub2) {
return sub1.getName() + sub2.howl();
}
}
复制代码
通配符的意义就是它是一个未知的符号,可以是代表==任意的类==,通常用?号表示.
作用:用于填充泛型变量T,表示代表任意类型!仅仅是填充方式的一种.
//使用位置有且只有,只能用来在生成泛型实例时使用. Location<?> location; location = new Location<Integer>(); 复制代码
Location<? extends Number> location; location = new Location<Integer>(2,3); //取 Number number = location.getX();//编译通过 //存 location.setX(new Integer(123);//编译报错 复制代码
location的类型由<? extends Number>决定,并不会因为location = new Location(2,3)而改变类型.所以不能确定通配符类型.
/** * 准备三个类Animal(动物),Mammal(哺乳动物),Mouse(老鼠). * Mouse 继承 Mammal, Mammal 继承 Animal. * .....省略相关类代码 */ List<? super Mammal> list; list = new ArrayList<Animal>; //取 Animal animal = list.get(0);//编译报错 Object object = list.get(0); //存 list.add(new Animal());//编译报错 list.add(new Mammal()); list.add(new Mouse()); 复制代码
取的时候报错,编译器不能确定<? super Mammal>的父类就是Animal.
至于存的时候报错,同样因为是未知类型,编译器只能确定通配符类型为Mammal及其子类.
最后的话:
本文只是对参考链接的内容总结,如需详细了解,请参考启舰大佬的博客链接.
由于本人技术有限,如有错误的地方,麻烦大家给我提出来,本人不胜感激,大家一起学习进步.
参考链接: