盒子
盒子
文章目录
  1. 元组类库
  2. 泛型的进一步使用
  3. 泛型方法
    1. 杠杆利用类型参数推断
    2. 泛型方法中的可变参数
    3. 泛型的擦除
      1. 解决方法

泛型

泛型出现于Java SE5,泛型的出现使编写可以应用于多种类型的代码成为可能,实现了参数化类型,而且解耦了类或方法与使用的类型之间的约束。

eg:

1
List<T>

该List容器可装入的对象类型定义为泛型,即没有明确规定要装生命类型的对象

元组类库

当需要通过return语句返回多个对象时,可通过创建一个对象,将需要返回的多个对象存在该对象中,这种对象就称为元组

注意:

该对象只允许读取其中的元素,而不允许像其中存入新对象,这也被称为数据传送对象或行使

元组的应用:

FirstTuple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class FirstTuple <A,B>{
private final A a;
private final B b;
public FirstTuple(A a,B b){
this.a=a;
this.b=b;
}
public A getA(){
return a;
}
public B getB(){
return b;
}
public String toString(){
return "A:"+a+" B:"+b;
}
}

SecondTuple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SecondTuple<A ,B,C> extends FirstTuple<A,B>{
private final A a;
private final B b;
private final C c;
public SecondTuple(A a,B b,C c){
super(a,b);
this.a=a;
this.b=b;
this.c=c;
}
public A getA(){
return a;
}
public B getB(){
return b;
}
public C getC(){
return c;
}
public String toString(){
return "A:"+a+" B:"+b+" C:"+c;
}
}

TupleUser:

1
2
3
4
5
6
7
8
9
10
11
12
public class TupleUser {
private static FirstTuple<String,Integer> f(String str,Integer inte){
return new FirstTuple<>(str,inte);
}
private static SecondTuple<String,Integer,String> s(String str,Integer inte,String stri){
return new SecondTuple<>(str,inte,stri);
}
public static void main(String...args){
System.out.println(f("fs",1));
System.out.println(s("ss",2,"ssi"));
}
}

由以上代码可知,通过泛型就可以灵活地将各种数据存入元组对象,数据类型可由客户端开发人员自己决定,而不用频繁地更改存储对象类

泛型的进一步使用

但不难发现以上功能通过定义超类Object类也可以实现,此时泛型的另一独到之处又体现出来,即是指定容器需要存放的对象类型,如:

1
List<String>

同时也可以实现”限定性的泛化”,即同时起到指定需要什么类型和先定义后决定用在限定范围内的具体类型。

应用如下:

1
2
3
public abstract  class ThirdTuple<T extends FirstTuple<String,Integer>> {
public abstract T f();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TupleUser extends ThirdTuple<TupleUser.ExtendFirstTuple>{
public static void main(String...args){
}
/* error:String类型不满足定义的泛型约束(T extends FirstTuple<String,Integer>)
@Override
public String f() {
return "f";
}
*/
@Override
public ExtendFirstTuple f() {
return new ExtendFirstTuple("str",1);
}
public class ExtendFirstTuple extends FirstTuple<String,Integer>{
public ExtendFirstTuple(String str, Integer inte) {
super(str, inte);
}
}
}

Android源码上的一个小应用:

1
2
3
4
@NonNull
public abstract static class RecyclerView.Adapter<VH extends ViewHolder> {
public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private class InerHolder extends RecyclerView.ViewHolder{
private TextView textView;
private InerHolder(@NonNull View itemView) {
super(itemView);
textView=findViewById(R.id.recycler_textView);
}
}
private class InerAdapter extends RecyclerView.Adapter<InerHolder>{
@NonNull
@Override
public InerHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new InerHolder(LayoutInflater.from(getApplicationContext()).inflate(R.layout.recycler_item,viewGroup,false));
}
@Override
public void onBindViewHolder(@NonNull InerHolder inerHolder, int i) {
inerHolder.textView.setText("i:"+i);
}
@Override
public int getItemCount() {
return 1;
}
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
}

若不使用泛型写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private class InerHolder extends RecyclerView.ViewHolder{
private TextView textView;
private InerHolder(@NonNull View itemView) {
super(itemView);
textView=itemView.findViewById(R.id.recycler_textView);
}
}
private class RecyclerAdapter extends RecyclerView.Adapter {
private Context context;
public RecyclerAdapter(Context context) {
super();
this.context=context;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new InerHolder(LayoutInflater.from(context).inflate(R.layout.recycler_item,viewGroup,false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
//此处若不想转型,可按第二种写法创建Adapter
((InerHolder)viewHolder).textView.setText("i:"+i);
}
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
@Override
public int getItemCount() {
//输出一个Item
return 1;
}
}

泛型方法

上面讲的都是类泛型,以下主要以方法泛型展开:

定义泛型方法秩序将泛型参数列表至于返回值前,eg:

1
public <T> void f(T t){}

杠杆利用类型参数推断

为了简化代码,可编写一个泛型工具类:

1
2
3
4
5
6
7
8
public class TUtil{
public static <k,V> Map<K,V> map(){
Map<K,V> map=new HashMap<K,V>();
}
public static final void main(String...args){
Map<String,String> maper=TUtil.map();
}
}

泛型方法中的可变参数

1
2
3
4
5
6
7
public class Ter{
public <T> void t(T...args){
for(T a:args){

}
}
}

泛型的擦除

Java泛型是使用擦出来实现的,在使用泛型时,任何具体的类型都会被擦除

如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class To{
public void f(){}
}
class Ter <T>{
public T t;
public Ter(T t){
this.t=t;
}
public void fer(){
//Erro:cannot find symbol
t.tf();
}
}
public class TerT{
public static final void main(String...args){
To to=new To();
Ter ter<To> ter=new Ter(to);
ter.fer();
}
}

由于To被擦除了类型,所以无法找到方法tf

解决方法

1
2
3
4
5
6
7
8
9
10
class Ter <T extends To>{
public T t;
public Ter(T t){
this.t=t;
}
public void fer(){
//Erro:cannot find symbol
t.tf();
}
}

T -> T extends To

使其擦除到To边界

支持一下
扫一扫,支持Grooter
  • 微信扫一扫
  • 支付宝扫一扫