Java的数据类型
Java的数据类型主要分为两大类:基本数据类型(Primitive Data Types)和引用数据类型(Reference Data Types)。
数据类型的核心作用是定义数据的性质、存储方式以及可进行的操作。
- 基本数据类型
Java 有 8 种基本数据类型,可进一步细分为 4 类:整数类型、浮点类型、字符类型和布尔类型。
整数类型
用于表示整数数值,不同的整数类型具有不同的取值范围和占用的存储空间。
byte:占8位(1字节),取值范围是-128到127。这种类型常用于存储二进制数据,比如声音、图像和文件等。其包装类是Byte。
byte num = 100;
short:占16位(2字节),取值范围是-32768到32767。这种类型主要用于节约内存空间,特别是在需要大量存储整数的地方。其包装类是Short。
short num = 2000;
int:占32位(4字节),取值范围是-2147483648到2147483647。这是Java中最常用的整型数据类型之一,几乎所有需要存储整数的场合都可以用到它。其包装类是Integer。
int num = 100000;
long:占64位(8字节),取值范围是-9223372036854775808到9223372036854775807。主要用于处理比int更大的整数数据,比如日期和时间。其包装类是Long。
long num = 10000000000L; (注意:long 类型赋值时需在数字后加 L 或 l)
浮点型
float:占32位(4字节),符合IEEE 754标准,可以表示小数点前8位和小数点后23位的数字。这种类型主要用于科学计算和需要高精度计算的场景。但需要注意的是,浮点数不能用来表示精确的值,如货币。其包装类是Float。
float num = 3.14f; (注意:float 类型赋值时需在数字后加 f 或 F)
double:占64位(8字节),符合IEEE 754标准,可以表示小数点前16位和小数点后53位的数字。这是Java中使用最广泛的浮点数类型,几乎所有需要高精度计算的场合都可以用到它。同样地,double类型也不能表示精确的值,如货币。其包装类是Double。
double num = 3.1415926;
字符型
char:占16位(2字节),使用Unicode字符集,可以表示Unicode字符集中的所有字符,包括字母、数字、符号和中文字符等。这种类型主要用于处理字符数据,比如字符串和文本。其包装类是Character。
char ch = 'A';
布尔型
boolean:占8位(1字节)(但实际上JVM可能会采用更高效的存储方式),只有两个取值:true和false。这种类型主要用于条件判断和布尔运算,比如控制流程和逻辑判断。其包装类是Boolean。
boolean isTrue = true;
基本数据类型的转换
在Java中,基本数据类型之间可以相互转换,这种转换分为自动类型转换(隐式类型转换)和强制类型转换(显式类型转换)。
自动类型转换:发生在从小范围类型向大范围类型转换时,如byte自动转换为int,short自动转换为long等。这种转换是由JVM自动完成的,不需要显式声明。
// byte -> short -> int -> long -> float -> double
byte b = 10;
short s = b; // 自动转换
int i = s; // 自动转换
long l = i; // 自动转换
float f = l; // 自动转换,注意:long到float可能会有精度损失
double d = f; // 自动转换
// char 到 int 的自动转换(因为char在内部是以整数形式存储的)
char c = 'A';
int ic = c; // 自动转换,'A' 的 ASCII 值是 65
System.out.println("byte to short: " + s);
System.out.println("short to int: " + i);
System.out.println("int to long: " + l);
System.out.println("long to float: " + f);
System.out.println("float to double: " + d);
System.out.println("char to int: " + ic);
强制类型转换:当一个较大的数据类型转换为较小的数据类型时,需要手动进行强制类型转换。这种转换可能会导致数据丢失或溢出,因此需要谨慎使用。
// double -> float -> long -> int -> short -> byte
// 注意:这些转换可能会导致数据丢失或溢出,因此在实际应用中需要谨慎
double d = 123.456;
float f = (float) d; // 强制转换,可能会有精度损失
long l = (long) f; // 强制转换,这里实际上是不安全的,因为float不能精确表示long能表示的所有值
// 但为了演示,我们假设转换是可行的(在实际中,通常不会直接从float转换到long)
int i = (int) l; // 强制转换,可能会导致数据丢失
short s = (short) i; // 强制转换,可能会导致数据丢失
byte b = (byte) s; // 强制转换,可能会导致数据丢失
// 演示从int到char的强制转换(通常用于获取字符的ASCII值或从ASCII值获取字符)
int num = 65;
char c = (char) num; // 'A' 的 ASCII 值是 65
System.out.println("double to float: " + f);
System.out.println("float to long then to int (unsafe): " + i); // 不安全转换的示例
System.out.println("int to short: " + s);
System.out.println("short to byte: " + b);
System.out.println("int to char: " + c);
- 引用数据类型
引用数据类型指向一个对象,而不是存储实际的数据值。常见的引用数据类型包括类(Class)、接口(Interface)、数组(Array)和枚举(Enum)等。
类(Class)
类是 Java 中最常见的引用数据类型,它是对象的模板,定义了对象的属性和行为。通过类可以创建多个具有相同属性和行为的对象实例。
当创建一个类的对象时,对象会被分配到堆内存中,而引用变量存储的是该对象在堆内存中的地址。
class Person {
String name;
int age;
}
public class Main {
public static void main(String[] args) {
Person person = new Person(); // 创建 Person 对象
// person 变量存储的是 Person 对象在堆内存中的地址
}
}
接口(Interface)
接口是一种抽象类型,它只包含方法的签名(方法名、参数列表和返回类型),不包含方法的实现。类可以实现一个或多个接口,从而实现接口中定义的方法。
接口的引用变量同样存储的是实现该接口的对象的地址。
interface Animal {
void eat();
}
class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog is eating.");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog(); // 创建 Dog 对象并使用 Animal 接口引用
// animal 变量存储的是 Dog 对象在堆内存中的地址
}
}
数组(Array)
数组是相同类型数据的有序集合,通过下标来访问数组中的元素。数组可以是一维的,也可以是多维的。
数组对象也存储在堆内存中,数组引用变量存储的是数组对象在堆内存中的地址。
public class Main {
public static void main(String[] args) {
int[] arr = new int[5]; // 创建数组对象
// arr 变量存储的是数组对象在堆内存中的地址
}
}
字符串(String)
String 类是 Java 中用于处理文本的引用数据类型。虽然在使用时感觉像基本数据类型,但实际上它是一个类。String 对象是不可变的,即一旦创建,其值不能被改变。
// 创建字符串对象
String str1 = "Hello";
String str2 = new String("World");
集合(Collection)
集合是 Java 中用于存储和操作一组对象的容器。
Java 提供了多种集合类,如 List、Set、Map 等,它们都位于 java.util 包中。
其他特殊的引用类型
强引用:默认情况下,对象都是强引用的,只要对象有强引用指向它,它就不会被垃圾回收器回收。
软引用:软引用通过SoftReference类实现,当内存空间足够时,软引用指向的对象不会被回收;当内存空间不足时,系统可能会回收软引用指向的对象。
弱引用:弱引用通过WeakReference类实现,无论内存空间是否足够,只要发生垃圾回收,弱引用指向的对象都会被回收。
虚引用:虚引用通过PhantomReference类实现,虚引用不能单独使用,必须与ReferenceQueue一起使用。当一个对象被垃圾回收器回收时,会将该虚引用加入到与之关联的ReferenceQueue中。