首页 > 编程知识 正文

java泛型 面试,泛型编程和模板的区别

时间:2023-05-04 15:49:54 阅读:137264 作者:3478

本文主要列举Java通用和Kotlin通用的基本知识以及两者的区别。

通用编程是指编程的风格或规范。 简单来说,它的类型是可变的,在编写代码时可以根据情况设置不同的类型。 由于通用的可变性,容易发生类型转换异常。 Java和Kotlin在编译过程中提供了通用的检查,以便开发人员在编译过程中尽量避免此异常的发生。

Java通用基础知识Java通用主要用于类、接口和类方法。 泛型类型只在编译过程中有效,编译完成后删除泛型类型标记。

//类class ObjectAT{}//接口interface InterfaceBT{}//方法privatetvoidfill (ArrayList numbers ) }总称子类的自动强类型父类

class parent { } classchildextendsparent { }//统称为parentobjectaparento=new object aparent (; 允许接收Parent的子类o.add (new child ); 泛型可以是子类的类型,但使用泛型的对象并不具有泛型继承关系。 例如,以下内容:

私有对象文件(objectaparentobj )文件(newobjectAparent ); ); //该行中的代码报告错误,错误消息为:Child且无法转换为parent fill (newobjectachild ) ); 由此可见,泛型类型只能提供对象的类型判定,而不能自动进行类型转换。

也可以限制通用范围。 例如:

classobjectatextendsparent { public void add }由extends关键字表示,泛型类型只能为parent及其子类设置其他泛型类型错误。 通常,可以按以下方式默认设置extends :

classobjectaparent { } classobjectatextendsparent { }正如刚才所述,由于泛型类型具有自动向上强烈旋转的特性,因此这两种代码的作用相同,但从意义上来说,extends更像是但是,设置扩展可能会明显不同,如下所示:

arraylistparentparents1=new ArrayList (; ArrayList? extendsparentparents2=new ArrayList (; parents1.add(newparent ) ); //小心! 此行代码为parents2.add(newparent ) ); parentP1=parents1.get(0; parentP2=parents2.get(0; Java通用通配符,表示所有类型。 指定泛型类型时,如果使用了extends关键字,则只能在集合中添加Parent及其子类,但只能选择一个Parent子类。 例如,Parent有三个子类a、b和c,只能选择一个,但由于只能在运行期间知道具体是什么,因此无法获取Java,无法添加。

还有与extends对应的super关键字。 这表示只能添加,并且读取类型为Object。

//suer关键字是否指示只能输入Child及其父类的ArrayList? superchildchildren=new ArrayList (; Children.add(newchild ) ); //小心! 此行代码显示错误//childchild=Children.get(0; childchild=(child ) children.get(0) ) 0; 很多资料都说super被统称为Child的父类,但在实际使用中却不是这样。 他仍然是Child及其子类。 super关键字失去了意义,因为所有类型的基类都是Object。 因此,super的作用现在与extends的范围一致,但设计的思想相反,所以检索数据只能得到Object

因此,extends所限制的是输出类型的上限,可以归纳为super所限制的输入类型的下限。

Kotlin通用和Java通用的差异Kotlin通用和Java通用几乎相同,但不同的语言特性存在一些差异。

一. Java泛型不能调用泛型方法。 Kotlin不能用//Java语法直接调用通用的t的方法privatetvoidfill (ArrayList numbers ) Kotlin。 泛型类型t的方法inlinefunreifiedtprintgenerality (data : t ) println ) t:3360class.Java原因分析:泛型类型仅供编辑

译期间有效,运行期间会被擦除,所以泛型信息会消失,Java基于栈的形式调用方法得不到泛型的具体类型,Kotlin通过内联机制,编译期间是把方法直接添加到了对应的代码中,不存在栈调用的问题,所以可以通过上下文推导出泛型的具体类型。

友情提示:内联方法慎用return,会导致调用方直接返回。

二、Kotlin的泛型的型变

以之前的Java代码为例:

private void fill(ObjectA<Parent> obj){}fill(new ObjectA<Parent>(););// 该行代码会报错,错误提示为:Child不能转换为Parentfill(new ObjectA<Child>());

虽然Child继承Parent,但是Java泛型无法推导出两者的继承关系,但是Kotlin的泛型可以:

val list1 = ArrayList<Number>()val list2 = ArrayList<Double>()fill(list1)fill(list2)private fun fill(list: List<Number>) {}

原因分析:Kotlin把泛型拆分为输入泛型和输出泛型,关键字为in和out,例如:

class ObjectA<in T, out E>(private val t: T, private val e: E) { // 泛型T仅可以出现在输入方法,例如setfun set(t: T) { this.t = t } // 泛型E仅可以出现在输出方法,例如get fun get() = e}

上面的代码指定了,泛型T为输入类型,表示T只能用在输入的位置,例如set方法,如果有getT方法则报错,泛型E规则与之相反。

Kotlin重写了List接口:

// 标记集合的类型为输出类型public interface List<out E> : Collection<E>

但是ArrayList则将泛型E既当做输入类型,也当做输出类型:

public class ArrayList<E>

所以调用方法 fill(list: List)时,判断out泛型是否一致,而Double可以向上强转为Number,所以检查通过。

总结Koltin的泛型用in修饰,表示此泛型只可出现在输入位置,支持类型型变,泛型使用out修饰,表示此泛型只可以出现在输出位置,支持类型的逆变。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。