在Java中,能够表示数值的数据类型有6种,主要分为两类,一类是可以表示小数的float和double类型,另外一类就是只能表示整数类型的byte、short、int和long类型了。这些基本类型对应的封装类型都继承了Number类,Number.java类的源代码如下:
public abstract class Number implements java.io.Serializable {
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
public byte byteValue() {
return (byte)intValue();
}
public short shortValue() {
return (short)intValue();
}
private static final long serialVersionUID = -8742448824652078965L;
}
可以看到,其实对于每个Number抽象类的实现类都实现了如上4个抽象方法,也就是说可以调用xxxValue()方法进行任意数值类型的转换。但是需要注意的是转换过程中各个类型所能表示的精度和范围。其实大家可能注意到了,抽象类中实现了对由int类型转换到byte和short类型的方法,其实就是执行类型的强制转换。但是没有对其它的转换类型进行实现,如提供将long类型转换为short、byte类型。可能Java设计师们是考虑到一种普通大众的情况吧,经常有人直接使用强制类型对int进行更小范围内的转换。
查看Byte.java源代码,如下:
// --------------byte与其他几种数值类型进行转换--------------------------
public byte byteValue() {
return value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return (int)value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return (double)value;
}
也是在执行类型的强制转换。所以说通过调用用方法得到的结果与我们强制类型转换后的结果一致,只是以面向对象的方法提供出来更加符合了Java的设计思想而已。下面来继续看一下Byte.java类中剩下的源代码吧。
public final class Byte extends Number implements Comparable<Byte> {
public static final byte MIN_VALUE = -128;// -2^8
public static final byte MAX_VALUE = 127;// 2^7-1
private final byte value;
// 构造函数
public Byte(byte value) {
this.value = value;
}
public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");
public static String toString(byte b) {
return Integer.toString((int)b, 10);
}
// 静态内部类
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}
// 将原始类型的byte转换为包装类型的Byte
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
// 由于int所能表示的范围包含了byte,所以完全可以按int型进行处理
public static byte parseByte(String s, int radix)
throws NumberFormatException {
int i = Integer.parseInt(s, radix);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException( "Value out of range. Value:\"" + s + "\" Radix:" + radix);
return (byte)i;
}
public static byte parseByte(String s) throws NumberFormatException {
return parseByte(s, 10);
}
public static Byte valueOf(String s, int radix)
throws NumberFormatException {
return valueOf(parseByte(s, radix));//等同于new Byte(Byte.parseByte(s, radix))
}
public static Byte valueOf(String s) throws NumberFormatException {
return valueOf(s, 10);
}
public static Byte decode(String nm) throws NumberFormatException {
int i = Integer.decode(nm);
if (i < MIN_VALUE || i > MAX_VALUE) throw new NumberFormatException("Value " + i + " out of range from input " + nm);
return valueOf((byte)i);
}
public String toString() {
return Integer.toString((int)value);
}
public int hashCode() {
return (int)value;
}
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
// 对两个Byte类型的数进行比较
public int compareTo(Byte anotherByte) {
return compare(this.value, anotherByte.value);
}
public static int compare(byte x, byte y) {
return x - y;
}
// 一个byte类型用8位表示,也就是一个字节
public static final int SIZE = 8;
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s, 10);
}
// ...
private static final long serialVersionUID = -7183698231559129828L;
}
从源代码中应该看出以下几点:
(1)由于Integer所能表示的数值类型比Byte要大,所以可直接将Byte类型转换为Integer类型,然后调用Integer类型对应的方法进行,如如上的方法中调用Integer.decode(nm)、Integer.toString()和Integer.parseInt(s, radix)来处理。
(2)类中valueof(byte b)方法和ByteCache()方法实现了数据的缓存功能。使用了私有的静态内部类来缓存Byte类型的所有数值,也就是-128~127。
Byte a=-122;
Byte b=-122;
System.out.println(a==b);// 值为true
public class test06 {
public static void main(String args[]) {
Byte a=8;
}
}
编译运行这个类后,查看二进制文件test06.class,如下:
// Compiled from test06.java (version 1.7 : 51.0, super bit)
public class test.test06 {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public test06();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 3]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: test.test06
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 1, Locals: 2
public static void main(java.lang.String[] args);
0 bipush 8
2 invokestatic java.lang.Byte.valueOf(byte) : java.lang.Byte [16]
5 astore_1 [a]
6 return
Line numbers:
[pc: 0, line: 5]
[pc: 6, line: 6]
Local variable table:
[pc: 0, pc: 7] local: args index: 0 type: java.lang.String[]
[pc: 6, pc: 7] local: a index: 1 type: java.lang.Byte
}
在main方法中的偏移量为2一行中发现,Java转为调用了valueOf(byte)方法来查找这个值,这就实现了Byte值的共享。
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
System.out.println(c == d);//true
System.out.println(e == f); // false
结果可想而知。