整数类型:byte,1字节,8位,最大存储数据量是255,存放的数据范围是-128~127之间。
整数类型:short,2字节,16位,最大数据存储量是65536,数据范围是-32768~32767之间。
整数类型:int,4字节,32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
整数类型:long,8字节,64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
浮点类型:float,4字节,32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
浮点类型:double,8字节,64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
字符型:char,2字节,16位,存储Unicode码,用单引号赋值。
布尔型:boolean, 1字节,8位,只有true和false两个取值
自动装箱(Autoboxing)和拆箱(Unboxing)是Java中用于在基本数据类型和其对应的包装类型之间进行转换的机制。这两种机制的目的是使代码更简洁和易读,同时提供类型安全性。
1、自动装箱:将基本数据类型的值自动封装成相应的包装类型对象。例如,将 int 转换为 Integer,将 double 转换为 Double,等等。这样做可以让你像操作对象一样操作基本数据类型。
Integer num = 42; // 自动装箱,将基本类型 int 转换为 Integer 对象
2、自动拆箱:将包装类型对象自动解封为基本数据类型的值。例如,将 Integer 转换为 int,将 Double 转换为 double,等等。这样做可以让你像操作基本数据类型一样操作包装类型对象。
int value = num; // 拆箱,将 Integer 对象转换为基本类型 int
如果包装类型对象为 null,会导致 NullPointerException 异常。
全局变量,又称为成员变量。可分为两种。
常量是一种特殊类型的变量,它们使用 final 关键字声明,表示它们的值在编译时就已经确定,不能被修改。通常使用大写字母表示,例如 PI。
在 Java 中,常量的内存位置可以根据常量的类型和声明方式而有所不同。常量主要分为以下几种类型:
1、字面常量(Literal Constants): 这些常量是编译时已知的固定值,它们直接包含在代码中,不占用额外的内存位置。例如,以下是一些字面常量的示例:
整数常量:如 42、-10。
浮点数常量:如 3.14、0.01。
字符常量:如 'A'、'1'。
字符串常量:如 "Hello"、"Java"。
布尔常量:true 和 false。
2、final 关键字声明的常量: 使用 final 关键字声明的常量会在编译时被初始化,并在运行时分配内存位置。这些常量通常被编译器优化,以便在运行时能够快速访问。例如:
final int MY_CONSTANT = 100;
3、枚举常量(Enum Constants): 枚举常量是在枚举类型中定义的,它们也在运行时分配内存位置。每个枚举常量都是该枚举类型的一个实例,因此它们具有自己的内存位置。例如:
enum Days { MONDAY, TUESDAY, WEDNESDAY }
4、静态 final 常量: 静态 final 常量通常用于类级别,它们在类加载时分配内存位置,可以通过类名直接访问。这些常量通常也会被编译器优化。例如:
public class Constants {
public static final int MAX_VALUE = 100;
}
这些变量属于类而不是对象,它们被所有该类的对象共享。类变量通常用 static 关键字声明,它们在类加载时初始化,并且在整个应用程序的生命周期内存在。
public class Person {
public static String common = "人类";
}
class Client {
public static void main(String[] args) {
//sout: 人类
System.out.println(Person.common);
}
}
又称为属性。这些变量属于对象的一部分,每个对象都有自己的一组实例变量。它们在对象创建时分配内存,并随着对象的生命周期而存在。实例变量在类的任何非静态方法中都可以访问。
public class MyClass {
// 实例变量
private String name;
private int age;
// 构造方法
public MyClass(String name, int age) {
this.name = name;
this.age = age;
}
// 实例方法,访问实例变量
public void displayInfo() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
public static void main(String[] args) {
// 创建对象并访问实例变量
MyClass obj1 = new MyClass("Alice", 25);
MyClass obj2 = new MyClass("Bob", 30);
obj1.displayInfo(); // 输出 obj1 的实例变量值
obj2.displayInfo(); // 输出 obj2 的实例变量值
}
}
局部变量声明在方法、构造函数或代码块内部,它们只在这些区域内有效,通常需要在使用之前显式初始化。局部变量的生命周期仅限于其所在的代码块。
public class LocalVariablesExample {
public void calculateSum(int a, int b) {
// 声明局部变量
int sum;
// 计算和并赋值给局部变量
sum = a + b;
// 输出结果
System.out.println("Sum: " + sum);
}
public static void main(String[] args) {
LocalVariablesExample example = new LocalVariablesExample();
example.calculateSum(5, 7); // 调用方法
}
}
基本类型的属性有默认值,如int型是0。
包装类型的属性没有默认值,都是null。
包装数据类型允许属性具有一个额外的状态,即 null。这对于表示属性未初始化或无效的情况非常有用。如果使用基本数据类型,无法区分一个属性是未初始化还是具有特定的有效值。
假设你有一个表示人员money的 POJO 类:
public class Person {
private Integer money;
// 构造函数、getter 和 setter 方法等
}
使用包装数据类型 Integer 来表示money允许你更清晰地表示属性的状态,例如:
Person person = new Person();
// 表示年龄未初始化
Integer money= person.getMoney();
if (money== null) {
System.out.println("moeny未初始化");
} else {
System.out.println("money为:" + money);
}
使用包装数据类型,你可以明确地表示属性是否已初始化。如果你使用基本数据类型 int 代替 Integer,那么在money未初始化的情况下,你将无法区分是未初始化还是具有某个有效值(例如,0)。这可能导致误解和 bug 的产生。
与 POJO 类属性类似,RPC 方法的返回值和参数也应该使用包装数据类型,以便能够明确地表示返回的结果或传递的参数是否存在、是否有效。
比如RPC调用中入参和回参有值是null,就可以知道是没有传输或传输错误。如果是基本数据类型,给你一个0,你知道是想给你0,还是没有传输,默认值是0。如果傻乎乎地存到了数据库0,在一些场景下会出问题的。
这里个人感觉还是看场景。
1、如果需要局部变量的状态有null的情况,就使用包装类型,如
//从数据库里查money,如果用户还没有存钱,money=null,如果存了50,又取了50,money=0
int money = orderDao.get(orderId);
这个时候取钱,会报NPE。
2、不需要null状态,并且大量计算。
Integer a=10;
a+=20;
先将10自动装箱,然后拆箱,+20后又装箱。如果设计大量这样的操作,还是比较耗时的,这个时候建议使用基本数据类型。