最近在学习java,java中的基本数据类型与C、C++有些不同。
基本类型与引用类型的区别: 1.基本类型与引用类型的组成 基本类型是一个单纯的数据类型,它表示的是一个具体的数字、字符或一个布尔值,例如100、'M'和true。对于引用类型,若一个变量引用的是一个复杂的数据结构的实例,则该变量的类型就属于引用类型,在引用类型变量所引用的实例中,不仅可以包含基本类型的变量,还可以包括对这些变量进行操作的行为。 例如:创建一个People类,该类中包含了一个short型的成员变量和一些String型变量,并且定义了对这些成员变量进行操作的方法,其代码如下: public class People{ private String id; //表示身份证号码 private String name; //表示姓名 private short age; //表示年龄 private String sex; //表示性别 public void setId(String id){ //设置成员变量id值的方法 this.id=id; } public String getId(){ //返回成员变量id值的方法 return this.id; } …//省略了其他成员变量的setXXX()与getXXX()方法 } 下面创建People类的两个实例,并分别通过变量you和me引用: People you=new People(); People me=new People(); 则变量you与me的类型为引用类型,并且引用的是类的实例,所以更具体的为类引用类型。对于类引用类型变量,通过运算符“.”就可以访问类中的成员变量和方法了。例如,通过以下代码分别为变量you与me所引用的实例设置成员变量name的值: you.setName("reader"); //设置name值为"reader" me.setName("MR"); //设置name值为"MR" 通过以下代码来输出引用变量you与me所引用实例的name值: System.out.println(you.getName()); //输出"reader" System.out.println(me.getName()); //输出"MR" 2.Java虚拟机的处理方式 对于基本类型的变量,Java虚拟机会根据数据类型为其分配实际占用的内存空间,如对int型变量为其分配32位内存空间并存放变量值。 而对于引用类型变量,Java虚拟机同样要为其分配内存空间,但该空间内存放的并不是变量所引用的对象,而是对象在堆区存放的地址。所以引用变量最终只是指向被引用的对象,而不是存储了被引用的对象,因此两个引用变量之间的赋值,实际上就是将一个引用变量存储的地址复制给另一个引用变量,从而使两个变量指向同一个对象。 例如:定义两个Book类型的类引用变量book1和book2,其中变量book1引用Book类的一个对象,book2不引用任何对象。 Book类中定义了一个float型成员变量price,表示价格,代码如下: public class Book{ private float price=50.0f; //float型成员变量price, 表示价格 private int store=100; //int型成员变量store, 表示库存 private String name; //String类型成员变量name, 表示书名 } 通过以下代码定义book1和book2引用变量。 Book book1=new Book(); Book book2=null; Java虚拟机为引用变量book1、book2及book1所引用对象的成员变量分配的内存空间如图1所示。 从图1可以看出变量book1引用了Book类的实例,book2没有引用任何对象,下面通过如下代码对book2变量进行赋值。 book2=book1 //将book1引用对象的地址复制给book2变量, book1与book2引用同一个Book实例
数据类型间的转换: 1基本数据类型之间的类型转换 2字符串与其他数据类型的转换 3引用类型间的类型转换
1.基本数据类型之间的类型转换 在Java语言中,当多个不同基本数据类型的数据进行混合运算时,如整型、浮点型和字符串型进行混合运算,需要先将它们转换为统一的类型,然后再进行计算。 基本数据类型之间的转换可以分为3种:自动类型转换、强制类型转换和通过包装类进行过渡转换。 自动类型转换 从低级类型向高级类型的转换为自动类型转换,Java编程人员无需进行任何操作,由计算机自动地转换数据的类型。低级类型指取值范围小的类型,高级类型指取值范围大的类型,如int型相对于short型是高级类型,而相对于long型则是低级类型。不同基本数据类型间的混合运算存在以下4种情况。 从低级类型向高级类型的转换通常是比较安全的,因为低级类型数据的取值范围包含在高级类型数据的取值范围内,不会出现数据溢出或精度下降的情况。但在个别情况下,自动转换就会导致数据溢出的现象,例如:
int num1=2147483647; //定义int型变量num1, 并赋值为int类型的最大值
char c='A'; //定义char型变量c, 并赋值为字符'A'
int num2=num1+c; //该表达式先将char型变量c转换为int型数据65, 然后相加
System.out.println(num2); //输出结果为: -2147483584
强制类型转换 如果把高级数据类型数据赋值给低级类型变量,就必须进行强制类型转换,否则编译出错。强制类型转换格式如下: (欲转换成的数据类型)值 其中“值”可以是字面常数或者变量,例如: byte b=3; int i1=261, i2; long L1=102, L2; float f1=1.234f, f2; double d1=5.678; short s1=65, s2; char c1='a', c2; s2=(short)c1; //将char型强制转换为short型, s2值为: 97 c2=(char)s1; //将short型强制转换为char型, c2值为: A b=(byte)i1; //将int型强制转换为byte型, b值为: 5 i2=(int)L1; //将long型强制转换为int型, i2值为: 102 L2=(long)f1; //将float型强制转换为long型, L2值为: 1 f2=(float)d1; //将double型强制转换为float型, f2值为: 5.678 byte bb=(byte)774; //强制转换int型字面常数774为byte类型, bb值为: 6 int ii=(int)9.0123; //强制转换double型字面常数9.0123为int类型, ii值为: 9 在进行强制类型转换时可能会导致数据溢出或精度降低。如上述代码中强制转换int型字面常数774为byte型后赋值给byte型变量bb,导致数据的溢出。因为整数774超出了byte类型的取值范围,所以在进行强制类型转换时,表示整数774的二进制数据流的前24位将被舍弃,所以之后赋值给变量bb的数值是低8位的二进制表示的数据, int型整数774强制转换为byte类型后赋值给byte型变量bb 再例如强制转换double型字面常数9.0123为int型后赋值给int型变量ii,使得小数部分被舍弃,导致数据精度的下降。 int ii=(int)9.0123 //将double型强制转换为int型, 使得精度下降, ii值为9
通过包装类进行过渡转换 所谓包装类就是用来封装基本类型数据的类,提供包装类的目的是为了能够将基本类型的数据视为对象来处理。Java为每一种基本数据类型都提供了包装类,如表1所示。
基本数据类型 对应包装类 byte java.lang.Byte short java.lang.Short int java.lang.Integer long java.lang.Long float java.lang.Float double java.lang.Double boolean java.lang.Boolean char java.lang.Character 利用包装类可以在基本数据类型间进行转换,其转换方法为:首先将某个基本类型的数据转换为对应的包装类,然后调用包装类对象的xxxValue()方法转换为其他的基本数据类型。例如将float型转换为int型,通过Float包装类进行转换。 int i; float f=12.345f; Float fpack=Float.valueOf (f); //将float型转换为其包装类Float, 即装箱操作 i=fpack.intValue(); //通过包装类Float的intValue()方法转换fpack为int型 System.out.println(i); //输出结果为: 12 ① 在进行类型转换时,被转换的变量的值并不会改变。如上述程序,float型变量f的值仍为12.345。 ② valueOf()方法为类中的静态方法,可以通过包装类直接进行调用,而xxxValue()是非静态方法,必须通过类对象进行调用。 将基本数据类型转换为其包装类还可以通过包装类的构造方法进行转换,例如将int型整数129转换为Integer类型: Integer num=new Integer(129) 各包装类所具有的xxxValue()方法如表2所示。
xxxValue()方法 包含该方法的包装类 转换结果类型 byteValue() byte Byte、Short、Integer、 Long、Float、Double shortValue() short intValue() int longValue() long floatValue() float doubleValue() double charValue() Character char booleanValue() Boolean boolean 通过包装类的xxxValue()方法进行的过渡转换,实际上采用的是强制类型转换的方法,例如Float类的intValue()方法,其源代码如下: public int intValue() {
return (int)value;
} 包装类具有的特点。
(1)Java中的包装类通过final修饰符被声明为“最终类”,因此它们不能被继承来创建子类。 (2)从JDK 1.5版本开始,允许包装类和基本数据类型进行混合算术运算,并且能自动进行装箱与拆箱的操作。而在这之前的JDK版本中,算术表达式中只允许基本数据类型进行算术运算,而且不能自动完成装箱与拆箱的操作。 例如: Integer num1=10; Integer num2=20; Integer num3=new Integer(30); int result1=num1+num2; //result1的值为: 30 int result2=num3+100; //result2的值为: 130 Integer num4=40*5; //num4的值为200
2.字符串与其他数据类型的转换 在Java语言中还提供了字符串与其他数据类型之间的转换,尤其是与基本数据类型和包装类间的转换,会被经常用到。 将其他数据类型转换为字符串 将其他数据类型转换为字符串存在两种方法:调用类的toString()方法和调用String类的valueOf()方法。 (1)调用类的toString()方法。若该类为基本数据的包装类,则可以使用带参数的或不带参数的toString()方法。
不带参数的toString()方法为类的非静态方法,所以必须通过类对象进行调用,例如将一个Integer对象转换为字符串: Integer num=new Integer(321); //定义一个Integer对象 System.out.println("result="+(num.toString()+100)); //调用Integer对象的toString()方法 //转换为字符串, 并与整数100进行 //运算, 然后输出计算结果 运行结果如下: result=321100 带参数的toString()方法为类的静态方法,所以可以通过类直接进行调用。方法中的参数应为与包装类对应的基本数据类型变量或字面常数,例如转换一个float类型数据为字符串: float f1=12.345f; System.out.println("result="+(Float.toString(f1)+1.02f)); //输出结果为: 12.3451.02 (2)调用String类的valueOf()方法。通过调用String类的valueOf()方法既可将包装类型数据转换为字符串,也可以将基本数据类型或字面常数转换为字符串,另外,在转换其他引用类型对象时,等价于调用该对象toString()方法。例如:分别转换float型数据为字符串、转换Double类型数据为字符串和转换FloatToString类对象为字符串。 public class FloatToString{ public static void main(String[] args) { float ff=48.563f; //定义一个float型变量ff, 并赋值为48.563 Double d=new Double(12.567); //创建一个Double对象 FloatToString myobj=new FloatToString(); //创建一个类对象 System.out.println(String.valueOf(ff)+10); //调用String的valueOf(float f)方法转换float型 运行结果如下: 48.56310 12.56710 com.yxq.StringChange.FloatString_Change_02@de6ced //数据为字符串, 然后与整数10进行运算 Java中的基本数据类型都可以通过String中对应的valueOf()方法转换为字符串,然而在String类中并没有提供valueOf(byte b)和valueOf(short s)方法来转换byte和short型数据为字符串,但如下的方法调用是合法的: byte b='a'; short s=123; System.out.println(String.valueOf(b)); //输出结果为: 97 System.out.println(String.valueOf(s)); //输出结果为: 123 将字符串转换为基本数据类型 通过包装类的parseXxx()方法可以将一个字符串转换为该包装类对应的基本数据类型,但要求字符串必须为数字形式,例如,int num=Integer.parseInt("123")是合法的,而int num=Integer. parseInt("abc")则会抛出“java.lang.NumberFormatException: For input string: "abc"”异常。各包装类所具有的parseXxx()方法如表3所示。
parseXxx()方法 转换结果类型 Byte.parseByte(String s) byte Short.parseShort(String s) short Integer.parseInt(String s) int Long.parseLong(String s) long Float.parseFloat(String s) float Double.parseDouble(String s) double Boolean.parseBoolean(String s) boolean
3.引用类型间的类型转换 引用类型间的转换有自动类型转换和强制类型转换两种方法。对于类引用类型,具有继承关系的类,即父类与子类之间才可以进行类型的转换。 当引用了某个子类的变量对引用该子类的父类的变量赋值时,会自动进行类型的转换;反之,父类对子类进行赋值时则需要进行强制类型转换。 例如:A为父类,B、C分别继承自类A,分别定义引用这3个类的变量,然后进行各种赋值操作。 定义引用变量: Object obj=new Object(); A objA=new A(); B objB=new B(); C objC=new C(); 子类对父类进行赋值: obj=objA; //编译成功, 将类A赋给直接父类Object, 会自动进行类型转换 obj=objB; //编译成功, 将子类B赋给间接父类Object, 会自动进行类型转换 objA=objC; //编译成功, 将子类C赋给直接父类A, 会自动进行类型转换 父类对子类进行赋值: objA=obj; //编译出错, 将父类Object赋给直接子类A时, 需要强制类型转换 objA=(A)obj; //编译成功 objB=obj; //编译出错, 将父类Object赋给间接子类B时, 需要强制类型转换 objB=(B)obj; //编译成功 objC=objA; //编译出错, 将父类A赋给直接子类C时, 需要强制类型转换 objC=(C)objA; //编译成功
两个子类间的赋值: 如果两个不同的子类继承自同一个父类,那么这两个子类之间也不能进行类型的转换,因为它们之间没有直接或间接的继承关系。 objB=objC; //编译出错, 不能从C类型自动转换为B类型 objB=(B)objC; //编译出错, 不能将C类型强制转换为B类型
如果声明了一个父类型的变量,但使其引用子类对象,在编译时,Java编译器是根据变量被显示声明的类型去编译,因此该变量的类型被看作父类类型,所以将其进行强制类型转换并赋给引用了另一个子类对象的变量时,编译成功。但在运行时将抛出java.lang.ClassCastException异常,因为这个变量实际引用的是子类对象,两个子类属于不同的类型,也没有继承关系,所以不能将一个子类转强制转换为另一个子类。 A objD=new C(); //objD变量被显示声明为A类型 objB=(B)objD; //编译时, objD的类型被视为A类型, 所以编译成功,
//但运行时抛出java.lang.ClassCastException异常 对于引用类型中的数组引用类型,任何的两个不同类型的数组间不能进行类型的转换,但可以将数组转换为java.lang.Object类。 Object objArray=new Object(); int num_I[]={1,2,3}; long num_L[]={4,5,6}; num_I=num_L; //编译出错, 数组引用类型间不能自动进行类型转换 num_I=(int[])num_L; //编译出错, 数组引用类型间不能进行强制类型转换 objArray=num_I; //编译成功 objArray=num_L; //编译成功
Java 中数据类型之间的转换 1. short-->int exp: short shortvar=0; int intvar=0; shortvar= (short) intvar 2. int-->short exp: short shortvar=0; int intvar=0; intvar=shortvar; 3. int->String exp: int intvar=1; String stringvar; Stringvar=string.valueOf (intvar); 4. float->String exp: float floatvar=9.99f; String stringvar; Stringvar=String.valueOf (floatvar); 5. double->String exp double doublevar=99999999.99; String stringvar; Stringvar=String.valueOf (doublevar); 6. char->String exp char charvar=’a’; String stringvar; Stringvar=String.valueOf (charvar); 7 String->int、float、long、double Exp String intstring=”10”; String floatstring=”10.1f”; String longstring=”99999999”; String doubleString=”99999999.9”; Int I=Integer.parseInt (intstring); Float f= Integer.parseInt (floatstring); Long lo=long. parseInt (longstring); Double d=double. parseInt (doublestring); 8 String->byte、short Exp String s=”0”; Byte b=Integer.intValue(s); Short sh=Integer.intValue(s); 9 String->char Exp String s=”abc”; Char a=s.charAt(0); 返回字符a 10 String-->boolean String s=”true”; Boolean flag=Boolean.valueOf (“s”);