java中类型转换异常问题 强制类型转换 您所在的位置:网站首页 转换器有问题会怎么样 java中类型转换异常问题 强制类型转换

java中类型转换异常问题 强制类型转换

2024-03-28 11:38| 来源: 网络整理| 查看: 265

https://blog.csdn.net/czengze/article/details/52976820

1.背景

      在Java中,之所以需要强制类型转换是为了防止程序员在不知情的情况下把A类型数据错当成B类型的数据。将一种类型的值赋给另一个类型的变量是很常见的,如果这两种是兼容的,那么Java将执行自动转换,例如int和long,将int类型赋值给long类型的变量,总是可行的。但不是所有的类型都兼容。例如,没有将double类型转换为byte型的定义。但是不兼容的类型之间的转换仍然是可能的。达到这个目的,就需要使用强制类型转换。完成两个不兼容类型的强制转换。

2.自动类型转换和强制类型转换

      在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需要强制转换。因为子类拥有比父类更多的属性、更强的功能,所以父类转换为子类需要强制。

      当我们用一个类型的构造器构造出一个对象时,这个对象的类型就已经确定的,也就说它的本质是不会再发生变化了。在Java中我们可以通过继承、向上转型的关系使用父类类型来引用它,这个时候我们是使用功能较弱的类型引用功能较强的对象,这是可行的。但是将功能较弱的类型强制转功能较强的对象时,就不一定可以行了。

[java]  view plain  copy Father father = new Son();  Son son = (Son)father;  //编译出错,ClassCastException  Father father = new Father();  Son son = (Son) father;         在第一个例子中,father被指向一个子类对象,子类也可以指向子类对象。而第二个例子中,father被传给一个父类对象,子类引用不能指向父类对象。即很重要的概念是:父类引用指向子类对象。将父类转换为子类之前,应该用instanceof检查。 [java]  view plain  copy static class One {      public void foo() {          System.out.println("One");      }  }  static class Two extends One {      public void foo() {          System.out.println("Two");      }      public void dosth(){          System.out.println("Two again");      }  }  public static void main(String[] args) throws Exception{      One t = new Two(); //向上转型,即父类引用指向子类对象,此时子类对象的类型为父类的类型      t.foo();      t.dosth();//编译错误      t = (Two)t;       t.dosth();//编译错误       ((Two) t).dosth();//编译成功  }  

向上转型是安全的,但是会有些子类特性会丢失,向下转型可以成功。

      总结:父类引用可以指向子类对象,子类引用不能指向父类对象。把子类对象直接赋给父类引用叫做向上转型,向上转型不用强制转型,如Father f1=new Son(),把指向子类对象的父类引用赋给子类引用叫做向下转型,要强制转型,如Son s1 = (Son)f1。向上转型会丢失子类特有的方法,但是子类overriding父类的方法,子类方法有效。 

      将一种类型的数据赋给另外一种类型变量时,满足下列两种要求将执行自动类型转换:1.两种类型是兼容的;2.目的类型的范围比来源类型大。   

      数据值类型按照范围从小到大为:byte,short,char,int,long,float,double

      例如int类型比所有byte合法类型大,因此不要求显式强制类型转换。对于数字类型,整型和浮点型都是彼此兼容的,但是数字类型和字符类型和布尔类型是不兼容的,字符类型和布尔类型也不是互相兼容的。

      自动类型转换不能满足所有的转换需求,比如int型变量赋值给byte型变量,这种转换不会自动进行,因为byte型比int型范围小。为了完成两种不兼容类型转换,需要用到强制类型转换。

      目标类型指定了要转换成为的类型。例如果将int型转为byte型,int型取值范围大于byte型,它的值将堆byte型范围进行取模。而把浮点型赋值给整数型,就会出现截断,截取掉小数部分。从其他数值类型转换为char类型时,必须进行强制转换。将char类型转换为其他数值类型时,除了byte、short必须强制转换之外,int、long、float、double都不用强制转换。

[java]  view plain  copy byte b;  int i = 257;  double d = 32.13;  b = (byte) i;  System.out.println("i and b = " + i + " " + b);  i = (int)d;  System.out.println("d and i = " + d + " " + i);  b = (byte)d;  System.out.println("d and b = " + d + " " + b);  byte e=(byte)130;   System.out.println(e);        /* * output i and b = 257 1 d and i = 32.13 32 d and b = 32.13 32 -126 */           当257要转换为byte时,byte的范围是256,所以取模的结果是1。浮点值赋给整数型,截断了小数部分。 [java]  view plain  copy short s = 1;  s= s + 1;//编译错误  short s1 = 1;  s1 += 1;         上述陷阱是s = s + 1,s + 1会隐式转换为int型,把int型号赋给short,会造成类型缺失。而s1 += 1相当于s1 = (short)(s1 + 1)会把s1 + 1强制转换为short类型,就不会报错。涉及到写代码的严谨性。

      对于自动装箱和自动拆箱,将一个基本数据类型转换为对应的引用类型时,不必强制转换。将一个基本数据类型的引用类型转换为基本数据类型时,也不必要强制转换。

[java]  view plain  copy int i1 = 10;  Integer iObj1 = i1;  Integer iObj2 = new Integer(10);  int i2 = iObj2;         在三目运算符中,会按照算术类型中的提升原则将两端操作提升至统一类型,如果两端有一个操作数是引用类型,则整个表达式结果用Object型表示。

[java]  view plain  copy byte b = 10;   short s = 20;   int i = (b == 10) ? b : s;   int i1 = 10;   String str = "Hello";   Object obj = (i1 == 10) ? i1 : str;  // 在这里变量i进行了自动装箱操作         int和String互相之间的转换,首先是int转String,有两种方法 [java]  view plain  copy int i = 12345;  String s = "";  s = i + "";  s = String.valueOf(i);        第一种方法,s = i + "";会产生两个String对象, s = String.valueOf(i);直接使用String的静态方法。

[java]  view plain  copy String s = "12345";  int i ;  i=Integer.parseInt(s);  i=Integer.valueOf(s).intValue();       第一种方法直接使用静态方法,不会产生多余的对象,但会抛出异常。第二种方法相当于new Integer(Integer.parseInt(s))也会抛出异常,但是会多产生一个对象。

      valueOf返回的是原对象,toString()返回的是字符串。

3.instanceof

      instanceof是Java二元操作符,测试左边对象是否是右边类的实例,返回boolean类型的数据,作用上可以避免强制类型转换失败。

4.JVM级别原理

      对于强制类型转换,且是引用类型,如果是父类向子类转换,这种只牵扯到引用名义类型的转换,具体的内存没有什么变化。

      而基本类型转换不同,数据发生了变化。但是基本数据类型不是对象,如果涉及到自动装箱和拆箱,实际上是调用类似Integer.parseInt()和Integer.valueOf()实现。

      父类向子类强制转换,如果成功不会有任何数据丢失,如果不是子类,那么会报错。基本类型之间的转换,如果是大范围向小范围的转换,有可能发生数据丢失或者精确丢失。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有