Java泛型程序设计

为什么要有泛型程序设计?

        在没有泛型程序设计之前,程序员必须使用Object编写适用于多种类型的代码。这很繁琐,也很不安全。这种方法就存在两个问题:1. 当获取一个类的时候必须进行强制类型转换。2.没有类型检查,任何类都可以进行操作。

        泛型提供了一个更好的解决方案:类型参数。例如:List a = new ArrayList<String>;这是得代码具有更好的可读性。编译器也可以充分利用这个类型信息。调用get的时候不需要强制类型转换。编译器知道返回的类型是String。编译器还可以检查,防止插入错误类型的对象。泛型使得你的程序更易读也更安全。

泛型的优点

那么泛型的优点就很显而易见了:

1.不需要进行强制类型转换,代码可读性高。

2.可以进行类型检查,更加安全。

种类

       T:表示确定的类型,最常用的泛型表示方法。
  ? :表示不确定的类型,类似于通配符。
  K:一般用于键值对中的 –>键
  v:一般用于键值对中的 –>值
  E:表示枚举。

通配符类型

首先通配符有三种:

1.<?> 无限定通配符

2.<? extends ... & ...>上界通配符,限定上界

3.<? super ... & ...>下界通配符,限定下界

& 用于连接多种类

为什么需要通配符

第一种情况:我们需要对数据进行排序,需要调用compareTo方法,但是并非所有类都有这个方法,所以这时候会有问题出现。

对于这种情况可以用上界通配符解决,<T extends Comparable>,限定这个类必须实现Comparable接口。

这里为什么不用implements关键字?

因为T应该是限定类型的子类型。T和限定类型可以是类,也可以是接口。选择关键字extends的原因是它更接近子类型的概念,并且Java的设计者也不打算在语言中再添加一个新的关键字。

第二种情况:Comparable是一个泛型接口,把上述方法做的更好一点应该这样写:<T extends Comparable<T>>。但是这个类如果没有实现compareTo方法,我们想要调用超类的compareTo方法这种情况就不适用了。比如LocalDate实现了ChronoLocalDate,实现的是Comparable<ChronoLocalDate>。这时候要<T extends Comparable<? super T>>。

无界通配符Pair<?>初看和原始的Pair类型一样,但是实际上有很大的区别。

? getFirst()

void setFirst(?)

getFirst返回值只能赋给一个Object。setFirst方法不能被调用,甚至不能用Object调用。 

讲人话就是:?是一个范围,getFirst不知道返回的具体值,只能给Object,setFirst不知道具体值,不能用。

类型擦除

原因:虚拟机中没有泛型类型对象------所有类型都属于普通类。所以类型检查发生在编译时期。

无论何时定义一个泛型类型,都会自动提供一个相应的原始类型。这个原始类型的名字就是去掉类型参数后的泛型类型名。类型变量会被擦除,并替换为其限定类型。如果没有限定类型替换为Object,如果有多个替换为第一个。

为了提高效率,应该将标签接口如Serializable放在限定列表的末尾,避免多余的强制类型转换。

类型擦除出现的问题

DateInterval类覆盖了父类Pair的setSecond方法。

class DateInterval extends Pair<LocalDate>
{
    public void setSecond(LocalDate second) 
    {
        if (second.compareTo(first) >= 0)
        {
            super.setSecond(second);
        }
    }
}

类型擦除后Pair的类型被擦除

class DateInterval extends Pair
{
    public void setSecond(LocalDate second) { ... }
}

类型擦除后,DateInterval继承了Pair的setSecond方法----> public void setSecond(Object second);

在多态下,我们创建一个Pair类型指向DateInterval类型,我们想要调用DateInterval类型的setSecond(LocalDate second)方法,结果会调用DateInterval的setSecond(Object second)方法。

问题在于类型擦除和多态发生了冲突。为了解决这个问题,编译器在DateInterval类中生成了一个桥方法。public void setSecond(Object second) { setSecond((LocalDate) second); }

假设实现了public LocalDate getSecond();方法也会有两个方法,另一个是public Object getSecond();在Java中是不合法的,但是在虚拟机中,会由4参数类型和返回类型共同指定一个方法。

例如Employee.clone()和Object.clone();称为有协变的返回类型。

java代码中,判断两个方法是否是同一个方法是根据方法的签名来决定的,方法的签名是不包含方法的返回值的,也就是“方法签名=方法名+参数”。那上面这个两个方法不就冲突了吗,没错,如果我们代码里面这样写确实是冲突了,但是Java虚拟机中的方法签名规则是不同的,其“方法签名=方法名+参数+返回值”,所以他是能正确区分两个方法的,所以字节码中是允许存在上面这种情况的。

当然这种情况不只是在使用泛型的时候会出现,当在重写方法时,指定了一个更加严格的返回值类型,虚拟机会帮我们生成桥方法。

总结

1.虚拟机中没有泛型,只有普通的类和方法

2.所有的类型参数都会替换为他们的限定类型

3.会合成桥方法来保持多态

4.为保持类型安全性,必要时会插入强制类型转换。

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
泛型在计算器Java程序中的作用是为了实现通用的计算功能。通过使用泛型,可以将不同类型的数据作为输入参数,并进行相应的计算操作。 在泛型计算器Java程序中,通常会定义一个泛型方法,该方法接收一个操作符和两个泛型参数,并返回一个BigDecimal类型的结果。这个方法会使用字符串来代替操作符进行判断和计算,因为字符串的处理更加方便和精确。通过将泛型参数转换为字符串,并使用BigDecimal类的方法进行计算,可以保证计算结果的精确性。 泛型计算器Java程序还可以使用其他Java的特性来扩展功能,比如使用枚举和Java.awt.Desktop工具。这些特性可以在代码中提供更多的计算功能,并且使程序更加实用和灵活。 总之,泛型在计算器Java程序中的作用是实现通用的计算功能,并通过使用字符串和BigDecimal类来提供精确的计算结果。同时,可以使用其他Java的特性来扩展程序的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [泛型和接口的方式设计一个计算器](https://blog.csdn.net/weixin_29233333/article/details/115079494)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [java版计算器](https://download.csdn.net/download/wataxi_1985/4144578)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值