Java中基本类型默认值
如果类的成员变量是基本类型,那么在类初始化时,这些类型将会被赋予一个初始值。
这些默认值仅在 Java 初始化类的时候才会被赋予。这种方式确保了基本类型的字段始终能被初始化(在 C++ 中不会),从而减少了 bug 的来源。但是,这些初始值对于程序来说并不一定是合法或者正确的。
所以,为了安全,我们最好始终显式地初始化变量。
基本类型 | 初始值 |
---|---|
boolean | false |
char | \u0000 (null) |
byte | (byte) 0 |
short | (short) 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
这种默认值的赋予并不适用于局部变量 —— 那些不属于类的字段的变量(即非成员变量)。
因此,若在方法中定义的基本类型数据,这里的变量 b 不会自动初始化为0,因而在使用变量 b 之前,程序员有责任主动地为其赋值(和 C 、C++ 一致)。如果我们忘记了这一步, Java 将会提示我们“编译时错误,该变量可能尚未被初始化”。这一点做的比 C++ 更好,在后者中,编译器只是提示警告,而在 Java 中则直接报错。
class demo{
int a;
public void show(){
int b; //报错:Unreachable statement
……
}
}
基本类型的存储
基本类型的创建,Java 使用了和 C/C++ 一样的策略,变量直接存储”值”,并置于栈内存中,因此更加高效。
Java 确定了每种基本类型的内存占用大小。 这些大小不会像其他一些语言那样随着机器环境的变化而变化。这种不变性也是 Java 更具可移植性的一个原因。
基本类型 | 大小 | 最小值 | 最大值 | 包装类型 |
---|---|---|---|---|
boolean | — | — | — | Boolean |
char | 16 bits | Unicode 0 | Unicode 216 -1 | Character |
byte | 8 bits | -128 | +127 | Byte |
short | 16 bits | - 215 | + 215 -1 | Short |
int | 32 bits | - 231 | + 231 -1 | Integer |
long | 64 bits | - 263 | + 263 -1 | Long |
float | 32 bits | IEEE754 | IEEE754 | Float |
double | 64 bits | IEEE754 | IEEE754 | Double |
void | — | — | — | — |
所有的数值类型都是有正/负符号的。布尔(boolean)类型的大小没有明确的规定,通常定义为取字面值 “true” 或 “false” 。基本类型有自己对应的包装类型,如果你希望在堆内存里表示基本类型的数据,就需要用到它们的包装类。
类型提升
对小于 int 的基本数据类型(即 char、byte 或 short)执行任何算术或按位操作,这些值会在执行操作之前类型提升为 int,并且结果值的类型为 int。若想重新使用较小的类型,必须使用强制转换(由于重新分配回一个较小的类型,结果可能会丢失精度)。通常,表达式中最大的数据类型是决定表达式结果的数据类型。float 型和 double 型相乘,结果是 double 型的;int 和 long 相加,结果是 long 型。
在“+”运算时,若表达式含有 String 类型数据,其他非字符串数据都将被转换为字符串形式并连接。(也就是说“+”是字符串运算符,而不是算术运算符)。
public class Test {
public static void main(String[] args) {
int x = 0, y = 1, z = 2;
String s = "x, y, z ";
System.out.println(s + x + y + z);
System.out.println("===========");
// 将 x 转换为字符串
System.out.println(x + " " + s);
System.out.println("===========");
s += "(summed) = ";
// 级联操作
System.out.println(s + (x + y + z));
System.out.println("===========");
// Integer.toString()方法的简写:
System.out.println("" + x + y);
}
}
输出结果:
x, y, z 012 // 结果中的“012”表明x+y+z没有进行算术运算
===========
0 x, y, z //最前面的“0”其实是字符串类型,已被编译器转换
===========
x, y, z (summed) = 3 //输出结果的“3”表明:括号 () 可以控制表达式的计算顺序,以便在显示 int 之前对其进行实际求和。
===========
01 //结果为“01”而不是“1”,即结果为字符串类型,也就是说,可以使用""(空字符串)与基本数据类型相连,实现基本数据类型转换为字符串,
//而不使用其包装类的静态方法或String类的静态方法。
高精度数值
在 Java 中有两种类型的数据可用于高精度的计算。它们是 BigInteger
和 BigDecimal
。尽管它们大致可以划归为“包装类型”,但是它们并没有对应的基本类型。
1. `BigInteger` : 不可变的任意精度的整数。所有操作中,都以二进制补码形式表示 BigInteger(如 Java 的基本整数类型)。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。
另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
2. `BigDecimal` : 不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。
因此,BigDecimal 表示的数值是 (unscaledValue × 10-scale)。
BigDecimal 类提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。toString() 方法提供 BigDecimal 的规范表示形式。
---两个类均属于java.math包。
Java没有sizeof
在 C/C++ 中,经常需要用到 sizeof()
方法来获取数据项被分配的字节大小。C/C++ 中使用 sizeof()
最有说服力的原因是为了移植性,不同数据在不同机器上可能有不同的大小,所以在进行大小敏感的运算时,程序员必须对这些类型有多大做到心中有数。例如,一台计算机可用 32 位来保存整数,而另一台只用 16 位保存。显然,在第一台机器中,程序可保存更大的值。所以,移植是令 C/C++ 程序员颇为头痛的一个问题。
Java 不需要 sizeof()
方法来满足这种需求,因为所有类型的大小在不同平台上是相同的。我们不必考虑这个层次的移植问题 —— Java 本身就是一种“与平台无关”的语言。
–《Thinking In Java》
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1401362462@qq.com