java中泛型的使用(一)

本文详细解析了Java泛型的概念,包括泛型类、泛型接口及泛型方法的定义与使用,阐述了泛型在集合中的应用,以及泛型在方法、接口和类中的不同表现形式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型,顾名思义,广泛的使用呗,所以不确定用到的是哪一块了,是具体的哪一个东西,给你一个范围一个东西自己去选
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。注意这里的类型只能时引用类型,不能时基本数据类型。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

泛型类


public class Generic< Q > {
private T key;
public Generic(Q key) { //泛型构造方法形参key的类型也为Q,Q的类型由外部指定
this.key = key;
}
}

就这样的,很简单,用“<”和“>”包起来了一个Q泛型,这个Q是什么,就是我们再创建类时具体传进去的类

比如:
Generic< String > newQ = new Generic< String >();

这样的传进去了一个Stirng对象。没什么好说的了,就基本就是这样。
常用的java集合中,就用到了许多泛型的知识

Person person = new Student(3, “df”);
person.s();
ArrayList< Person > list1 = new ArrayList< Person >();
list1.add(new Person(3));
list1.add(new Person(4));
ArrayList< Student > list2 = new ArrayList< Student >();
list2.add(new Student(3, “f”));
list1.addAll(list2);
ArrayList< faslkf > list3 = new ArrayList< faslkf >();
list3.add(new faslkf());
list1.addAll(list3);
String[] strings = new String[] {“a”,“b”,“c”};
List< String > bList = Arrays.asList(strings);
bList.add(“d”);
System.out.println(bList);
下面这个例子中list的addAll方法,原型如下
在这里插入图片描述
在参数中,用到了E泛型,其中?extends E表示任何继承E的子类都可以


泛型接口


泛型接口和泛型类基本都差不多,就像抽象类和接口有什么区别对吧,自己想一想就知道,顺便提一下,抽象类和接口的区别也是面试常常问的题目,上半年我面了三家,两家这么问的。

public interface Generator< T> {
public T next();
}
泛型接口使用有两种比较常用的方式

class FruitGenerator< T> implements Generator< T>{
public T next() {
return null;
}
}

这里我们直观看过去并不知道T的具体类型,所以在创建对象的时候,必须传入一个具体的类型来告诉编译器你是啥。

public class FruitGenerator implements Generator< String> {
private String[] fruits = new String[]{“Apple”, “Banana”, “Pear”};
public String next() {
Random rand = new Random();
return fruits[rand.nextInt(3)];
}
}
这个就是在类的定义的时候直接将String类型传给了接口,所以我们在创建对象时就不需要进行七七八八的传入操作了。其实最常用的应该也是第二种了,因为所谓接口,就是提供给各种实现类去实现,那么接口用泛型很OK,但是对于实现类,应该还是要针对一种具体的情况去分类实现,这也是编程中一种比较艺术的方式,如果把各种类型都集中到一个类实现,就像第一种,那就要求各种类型的业务要求有很高的集中度和相似度,才能够降低成本,不然,还是要针对各种类型去实现。所以在开发中,一般情况还是用的第二种。


泛型方法


先来看一个模板

/**
泛型方法的基本介绍
@param tClass 传入的泛型实参
@return T 返回值为T类型
说明:
1)public 与 返回值中间< T>非常重要,可以理解为声明此方法为泛型方法。
2)只有声明了< T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
3)< T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
*/
public < T> T genericMethod(Class< T> tClass)throws InstantiationException ,
IllegalAccessException{
T instance = tClass.newInstance();
return instance;
}
怎么说呢,不符合这种方式的都不是泛型方法

比如看看下面这种

public T a(){
}
这种只是引用了类中泛型T,并不是方法自己的泛型,你看类它用了自己的泛型,所以方法也应该用自己的泛型,而且再泛型类中,泛型方法可以和泛型类使用同一名字泛型

同时注意,这里有个比较特殊的方法,我们需要注意,就是静态方法,并不需要创建相应类的对象,我们研究静态方法的泛型的时候,也不需要类的信息,也根本不可能直到类的信息,所以,对于静态方法,我们不能使用类中的泛型和类定义的信息,比如下面
public class gei<T>{
	public static T ik(){//这里根本不能这样使用,因为再类加载的时候这个静态方法就加载进了虚拟机,再这种情况下,类根本还没有创建对象,所以根本没有通过创建对象传入相应的实际参数类,这时候静态方法根本不知道T是啥,所以静态方法不能使用类中的泛型。
	}
}

第二种情况:正确的静态方法使用情况
public static<T> T t() {
		return t();
}
当然这个例子会内存溢出,这里只是为了举个例子而已,定义正确的静态方法泛型就是这样的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小满锅lock

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值