Java泛型面试也能虐暴你

Java么么么——泛型

泛型是什么?

泛型就是将类型作为参数进行传递,当创建对象或者调用方法时才确定下具体的数据类型。并且泛型只能传递引用数据类型

为什么需要泛型?

在JDK5之前,对象是用Object来表示的,当要获取具体的对象时,就得进行强制类型转化,非常的麻烦。

比如要往一个集合Collection或者Map 中存放一个对象,存的是Object类型,例如往集合中存放了一个狗Dog对象,然后又往集合中存放了一个猫Cat类型的对象,当要从集合中get一个猫Cat对象时,就得进行类型的转化,比较麻烦,而当用泛型之后,可以将对象的类型作为参数进行传递,这样在具体要用什么对象时,就不用再进行类型转化了。

因此总结起来,使用泛型的好处是:可以让代码更加简洁,因为不用进行强制类型转换;

让程序更加稳健,因为使用泛型在编译阶段没有报错的话,在运行阶段也不会报ClassCastException异常;

怎么使用泛型?

1.定义在类上的泛型 – 泛型类

将泛型定义在类上,这样类的方法也可以使用,当具体要new对象时,用户想要指定哪种类型,该泛型类就可以自动转化为对应的对象类型

2.派生类的泛型

2.1子类有明确泛型的类型

子类有明确泛型的类型,在实现接口时,实现类不用定义出泛型类型

2.2.子类没有明确泛型类型

子类没有明确泛型的类型,在实现接口时,实现类需要定义泛型类型

3.定义在方法上的泛型 – 泛型方法

当只需要在某个方法上应用泛型时,就不用直接定义在类上,直接在方法上定义就可以了。

4.泛型类型通配符

当一个方法中要接收一个集合作为参数时,想要遍历集合并把集合打印出来时,要想明确集合中的对象类型,

如果传的的话,这个在集合遍历时与这些是没有关系的,所以Java泛型提供了类型通配符

类型通配符?可以匹配任何的Java类型。当我们使用?号通配符的时候:就只能调对象与类型无关的方法,不能调用对象与类型有关的方法。

4.1通配符上限

如果接收一个List集合,它只能操作数字类型的元素【Float、Integer、Double、Byte等数字类型都行】,如果直接使用通配符,那么该集合就不只能匹配数字了,而是任意的Java类型,因此可以设定泛型的通配符上限

例如

List<? extends Number>
4.2通配符下限

类似于通配符上限,下限传递的类型限定只能是某种数据类型及其它的父类。

例如:

	//传递进来的只能是Type或Type的父类
	<? super Type>

注:大多数时候可以用泛型方法来代替泛型通配符

题目例子:

List< ? extends T > 和 List < ? super T > 之间有什么区别 ? ------ 这两个 List 的声明都是限定通配符的例子,List< ? extends T > 可以接受任何继承自 T 的类型的 List,而List < ? super T > 可以接受任何 T 的父类构成的 List。

5.泛型的类型擦除

类型擦除:泛型只作用在编译阶段,用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。当编译器编译完带有泛型的程序后,生成的class字节码文件是不带有泛型的,也就是说在运行阶段不存在任何类型相关的信息。这样使得程序运行的效率不会受影响,是确保能和 Java 5 之前的版本开发二进制类库进行兼容。这个过程称为类型擦除。

在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 < T > 则会被转译成普通的 Object 类型,如果指定了上限如 < T extends String > 则类型参数就被替换成类型上限。

  List<String> list = new ArrayList<>();

        //类型被擦除了,保留的是类型的上限,String的上限就是Object
        List list1 = list;

泛型可以用在哪里?-- 泛型的应用

比如在做项目时,对于Dao层,我们有很多的Dao接口类要编写,而这些Dao接口类都有 一个共同的点就是对数据进行增删改查,因此我们就可以定义一个抽象的Dao泛型类,在里面编写增删改查的方法,这样当有具体的Dao接口去继承它时,再去传递具体的数据类型即可。

例如:

抽象的Dao泛型类

public abstract class BaseDao<T> {

	//模拟hibernate....
	private Session session;
	private Class clazz;
	
	
	//哪个子类调的这个方法,得到的class就是子类处理的类型(非常重要)
	public BaseDao(){
		Class clazz = this.getClass();  //拿到的是子类
		ParameterizedType  pt = (ParameterizedType) clazz.getGenericSuperclass();  //BaseDao<Category>
		clazz = (Class) pt.getActualTypeArguments()[0];
		System.out.println(clazz);
		
	}
	

	public void add(T t){
		session.save(t);
	}
	
	public T find(String id){
		return (T) session.get(clazz, id);
	}
	
	public void update(T t){
		session.update(t);
	}
	
	public void delete(String id){
		T t = (T) session.get(clazz, id);
		session.delete(t);
	}
	
}

其他的具体类型的Dao接口类只要继承这个BaseDao接口,就有进行对应类型的增删改查操作

例如:

public class BookDao extends BaseDao<Book> {
//这个类型就可以进行Book的增删改查操作
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值