java泛型

1.概念
形参:是声明函数时写的。实参:调用方法时传入的值。
泛型也叫‘参数化类型’,在不创建新类型的情况下,通过泛型指定不同类型来控制形参,具体限制类型。
在泛型的使用过程中,操作的数据类型被指定为一个参数类型。

例: List array = new ArrayList();
这时的array可以add字符串和数字类型。当使用时,都以String类型使用时就会报错。
List<String> array = new ArrayList<String>();
这时add类型为Integer时会报错。编译器会在变异阶段发现这种问题。

2.特性
泛型只在编译阶段有效,不会进入运行时阶段,即在add等操作的阶段。

List<String> a= new ArrayList<String>();
List<Integer> b= new ArrayList<Integer>();
Class classA = a.getClass();
Class classB = b.getClass();
classA.equals(classB) 输出 true;

所有泛型类型在逻辑上是多个不同类型,但事实都是相同的基本类型。

3.使用(泛型类、泛型接口、泛型方法)

a.泛型类
常见的泛型容器有List、Set、Map.
一个普通泛型类:

public class A<T>{
private T key;//这里的T类型由外部指派
}
当实例化或者调用时,泛型类的类参数只能是类(包括自定义类),不能是简单类型。
A<Integer> a = new A<Integer>();

当不传入类型实参时,在泛型类中,使用泛型方法和成员变量的类型可以是任意的。
A a1 = new A(111);
A a2 = new A("www");
A a3 = new A(true);
  • *泛型类的类参数只能是类(包括自定义类),不能是简单类型。
  • *不能对有确切泛型类型的泛型类进行instanceof操作。(即A不能,A能)

b.泛型接口
泛型接口和泛型类的使用和定义基本相同。

public interface Face<T>{
private T getKey();//这里的T类型由外部指派
}

//当实现泛型接口,传人实参时:方法中的T要和传入类型一致
public class FaceImpl implements Face<String>{
  @override
  public String getKey(){
    return "111";
  }
}

//当实现泛型接口,不传人实参时:声明类后面也要加<T>.
public class FaceImpl<T> implements Face<String>{
  @override
  public T getKey(){
    return null;
  }
}

! 泛型通配符

//Integer和Number是一个子类。
public void getValue(A<Integer> i){}
//当调用该方法时,传人参数是A<Number>类型的实参时,编译器会报错。

public void getValue(A<?> i){}
//**?** 只作为**类型实参**,并不是泛型方法。这样就可以传递不同的类型的参数。

c.泛型方法
泛型方法: 在调用泛型方法时需指明具体类型。

//只有声明了<T>才算泛型方法,传入类型实参也可以为T。
public <T> T getValue(A<T> A){return null;}
public <T,K> K getValue(User<T> t){return null;}//泛型的数量可以是多个的

//在A<T>类中下面的方法不是泛型方法,虽然其使用了了泛型,但是该泛型是已经声明过的泛型。其只是一个普通的成员方法。
private T name;
public T getName(T name){return null;}
//如果不定义name则上面的方法就是错误的。

类中的泛型方法:

public class user<T>{
//当泛型类中声明泛型方法<K>,因为泛型方法在声明的时候会声明<K>,所有即使user类没有声明,编译器也能正常编译。
public <K> void getName(K name){}//K是调用方法时要指明的具体类型,要在public和void之前声明
private T id;
public <T> void getId(T id){}

//前提:Apple是Fruits的子类;实例化apple
User<Fruits> user = new User<Fruits>();//实例化User;
//在调用该类方法时可以用user.getId(apple);    因为Apple是Fruits的子类

//调用getName时可以传人无关类People;   user.getName(people);
}

泛型参数和可变参数

public <T> viod getName(T... names){
  for(T name: names){
   //这块可以打印出不同类型的name;
  }
}

static方法无法访问泛型类型的参数,如果要使用泛型能力,则必须成为泛型方法。而且静态方法只能访问静态成员。

泛型的上下边界:
在泛型的使用过程中,可以限制其传入某种类型的父类或其子类。

public void getType(User<? extends Number>){}
//这样只能传入Number的子类

public class User<T extends Number>{}
User<String> user = new User<String>();//因String不是Number的子类实例化时会报错。

方法:权限 和 返回类型之间声明
public <T extends Number> T getName(User<T> user){}

泛型数组
首先,java中不能创建一个确切泛型类型的数组。

可以使用通配符来创建泛型数组。(再次说明 ? 是类型实参)
List<?>[] s = new ArrayList<?>[10]; //其中的 ?可以写成Integer、String等。

对泛型数组的声明进行限制,可以在编辑器提示代码有类型安全问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值