你真的了解JAVA类型转换吗?

JAVA类型转换

Java类型转换主要包括以下八种
一、身份转换 (Identity Conversion)
A conversion from a type to that same type is permitted for any type.

This may seem trivial, but it has two practical consequences. First, it is always permitted for an expression to have the desired type to begin with, thus allowing the simply stated rule that every expression is subject to conversion, if only a trivial identity conversion. Second, it implies that it is permitted for a program to include redundant cast operators for the sake of clarity.

假装懂了(大误)

是指相同类型之间的转换,判断是否同类型可以通过instaceof判断。

二、小范围到大范围转换(Widening Primitive Conversion)

包含十九种类型;

  • byteshort, int, long, float, or double
  • shortint, long, float, or double
  • charint, long, float, or double
  • intlong, float, or double
  • longfloat or double
  • floatdouble

其中float ➡ double不用strictfp声明进行转换的话也有可能损失信息。

intfloat,

longfloat,

longdouble,

可能导致精度的损失 -也就是,其结果可能会丢失一些值的至少显著位。在这种情况下,使用IEEE 754舍入到最近模式,结果浮点值将是整数值的正确舍入版本。

合法转换

大范围向小范围转换( Narrowing Primitive Conversion)

包括22种

shortbyte or char

charbyte or short

intbyte, short, or char

longbyte, short, char, or int

floatbyte, short, char, int, or long

doublebyte, short, char, int, long, or float

以上都有可能(包括范围内的值转换)导致精度损失或者数据范围出错。

进行大范围向小范围转换首先应明确数值类型编码格式,特别是有符号和无符号值间转换,浮点型值转换。float跟double接受的都是IEEE 754舍入规则,但是表示同一数值的时候并不完全一样,如何进行值范围内的转换可以使用投射。

byte to char

是一种特殊的转换,将byte扩大转换为int,再将int缩小转换为char,因此也存在超出范围的情况。

三、扩大引用转换(Widening Reference Conversion)

指的是父类与子类之间的转换.

子类转换成父类

子类的实例自动转换给父类的引用,子类的新增属性、重写方法都保留。转换为父类后默认调用重写之后的方法。

四、缩小引用转化(Narrowing Reference Conversion)
父类转换成子类有六种情况

1、从类型到任何其他引用类型。

2、任何类型C到任何非参数化接口K,前提是C类不是final声明的,并且不实现K接口。

3、从任何类型J到非参数化类型C,并且C不是final声明的。

4、从任何接口J到任何非参数化接口K,并且J不是K的子接口。

5、从接口Cloneable和java.io.Serializable到任何数组类型

6、从任何数组类型SC到任何数组类型TC,并且SC和TC是引用类型,转换是缩小引用。

这些转换需要在运行时(RUNTIME)进行测试,使劲引用之是否符合新类型的合法值,否则抛出一个ClassCastException。

五、装箱(Boxing Conversion)

共有九种类型进行装修转换

  • booleanBoolean
  • byteByte
  • shortShort
  • charCharacter
  • intInteger
  • longLong
  • floatFloat
  • doubleDouble
  • null ➡ null

装箱时如果是boolean、byte、short、char、int、long则直接转换为相应的包装类的引用,对应其包装类的Value方法能获得值。

如果是float、double,如果不是NaN,装箱则转换为引用。否则将转换为一个参考r的,使得r.isNaN为true。

如果要装箱的值 是int 介于-128和之间127的整数文字,或者布尔文字truefalse或者介于'\u0000'和之间的字符文字'\u007f'则默认装箱结果引用同一值。具体表现为如果直接使用==判断他们的包装类时结果为true。

六、拆箱(Unboxing Conversion)

拆箱过程是相应的包装类调用**Value()方法将值赋给基本类型,

如果是null则抛出NullPointerException异常。

七、未经检查的转换(Unchecked Conversion)

未检查的转换是指多类型数组,进行转换。会在编译时报SuppressWarnings。

未检查的转换用于使遗留代码(在引入泛型之前)与经过转换以使用泛型(我们称为泛化的过程)的库之间实现平滑的互操作。在这种情况下(最值得注意的是,中的Collections Framework的客户端java.util),旧代码使用原始类型(例如Collection而不是Collection)。原始类型的表达式作为参数传递给使用相同类型的参数化版本及其相应形式参数的类型的库方法。

在使用泛型的类型系统下,无法证明此类调用在静态上是安全的。拒绝此类调用会使现有代码的大部分无效,并阻止它们使用库的较新版本。反过来,这将阻止图书馆供应商利用通用性。为了防止发生这种不受欢迎的事件,可以将原始类型转换为原始类型所引用的泛型类型声明的任意调用。尽管转换不合理,但为了实用性可以容忍。在这种情况下,将发出未经检查的警告。

八、捕获转换(Capture Conversion)

通常情况下,使用原生类型和<?>并没有什么区别,但是有一种情况特别需要使用<?>而不是原生类型,即捕获转换(因为未指定的通配符类型被捕获,并被转换为确切类型)。

   static <T> void f1(Holder<T> holder){
   ...
    }
    static void f2(Holder<?> holder){
        f1(holder);
    }

捕获转换允许我们在处理通配符时绕开编译器的限制。当f2() 调用 f1() 时,它知道这么做是安全的,因为它自身的 holder 参数对一些未知的 V 而言一定是Holder。同时类型参数 T 被引入到方法签名中并且没有绑定到其他任何类型参数,它也可以表示任何未知类型,因此,某些未知 T 的 Holder 也可能是某些未知 V 的 Box。

f1()中的类型参数都是确切的,没有通配符或者边界。在f2()中,Holder参数是一个无界通配符,因此它看起来是未知的。但是,在f2()中,f1()被调用,参数类型在调用f2()的过程中被捕获,因此它可以在对f1()的调用中被使用。

捕获转换只有在这样的情况下可以工作:即在方法内部,你需要使用确切的类型。

注意:不能从f2()中返回T,因为T对于f2()来说是未知的。

一般来说,带有通配符的 API 比带有泛型方法的 API 更简单,在更复杂的方法声明中类型名称的增多会降低声明的可读性。因为在需要时始终可以通过专有的捕获转换来恢复名称,这个方法可以保持 API 整洁,同时不会删除有用的信息。

参考:java 捕获转换

九、字符串转换(String Conversion)
Int,Double, Float, Long转String

A、String s = String.valueOf(i);

public static String valueOf(Object obj){return (obj==null) ? “null” : obj.toString()};

B、String s = Integer.toString(i);

C、String s = “” + i;

D、Stirng s = (String)i;

A、B、C本质都一样,都是调用了toString()方法,不过A相对安全,对对象做了一个非空判断。D、需要确定是字符串类型。

String 转 数值

A、 int i = Integer.parseInt([String]);

#直接将String转换为10进制Int,如果存在非法字符则抛出异常。

B、i = Integer.parseInt([String],[int radix]);

#将Sting通过指定进制的字符串转换为十进制的Int。

C、int i = Integer.valueOf(my_str).intValue();

#Integer.valueOf().intValue()会比Integer.parseInt()多创建一个Integer对象,实际调用的还是parseInt方法。

十、值集转换(Value Set Conversion)

值集转换是将浮点值从一个值集映射到另一个值集而不更改其类型的过程。

在不受FP限制的表达式中,值集转换为Java编程语言的实现提供了选择:

  • 如果该值是float-extended-exponent值集的元素,则实现可以选择将值映射到float值集的最接近元素。此转换可能导致上溢(在这种情况下,该值被相同符号的无穷大代替)或下溢(在这种情况下,该值可能会失去精度,因为该值被非规范化的数字或相同符号的零所代替)。
  • 如果该值是double-extended-exponent值集的元素,则实现可以选择将值映射到double值集的最接近元素。此转换可能导致上溢(在这种情况下,该值被相同符号的无穷大代替)或下溢(在这种情况下,该值可能会失去精度,因为该值被非规范化的数字或相同符号的零所代替)。

在FP限制表达式中,值集转换不提供任何选择;每个实现都必须以相同的方式表现:

  • 如果值是类型float且不是浮点值集的元素,则实现必须将值映射到浮点值集的最接近元素。此转换可能导致上溢或下溢。
  • 如果该值是类型double且不是double值集的元素,则实现必须将值映射到double值集的最接近元素。此转换可能导致上溢或下溢。

在FP-strict表达式中,仅当调用方法的声明不是FP-strict且实现选择了表示结果时,才需要从float-extended-exponent值集或double-extended-exponent值集中映射值。方法调用作为扩展指数值集的元素的过程。

无论是在FP严格代码中,还是在非FP严格代码中,值集转换始终使类型为float或的 任何值保持不变double

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值