java判断变量类型-Java语言中基本类型的存储范围有哪些?
public class Main {
public static void main(String[] args) {
byte b = 1;
short s = 1;
int i = 1;
long l = 1L; // 一般我们会使用大写的 L 作为后缀表示,因为小写的 l 不易区分
float f = 0.1f;
double d = 0.1;
char c = '1';
boolean flag = true;
}
}
Java 语言中也提供了几种利于表示数字的表示机制,比如我们可以使用 “_” 来分割数字,这样我们就可以清晰地知道一个大数是多少
public class Main {
public static void main(String[] args) {
int a = 10_0000_0000; // 我们可以很清晰地知道 该数字为 10 亿
}
}
同时,也有科学记数法表示:
public class Main {
public static void main(String[] args) {
int a = (int) 1e8; // 该数字为 1 亿
}
}
各个基本类型的存储范围
它们表示的存储范围,我们可以通过各个基本类型对应的包装类的 MIN_VALUE 和 MAX_VALUE 得知:
public class Main {
public static void main(String[] args) {
System.out.println("byte 存储范围:" +Byte.MIN_VALUE+" ~ " +Byte.MAX_VALUE);
System.out.println("short 存储范围:" +Short.MIN_VALUE+" ~ " +Short.MAX_VALUE);
System.out.println("int 存储范围:" +Integer.MIN_VALUE+" ~ " +Integer.MAX_VALUE);
System.out.println("long 存储范围:" +Long.MIN_VALUE+" ~ " +Long.MAX_VALUE);
System.out.println("float 存储范围:" +Float.MIN_VALUE+" ~ " +Float.MAX_VALUE);
System.out.println("double 存储范围:" +Double.MIN_VALUE+" ~ " +Double.MAX_VALUE);
System.out.println("char 能够存储一个字符,消耗两个字节的空间");
System.out.println("boolean 只能表示 true 和 false");
}
}
程序输出结果为:
byte 存储范围:-128 ~ 127
short 存储范围:-32768 ~ 32767
int 存储范围:-2147483648 ~ 2147483647
long 存储范围:-9223372036854775808 ~ 9223372036854775807
float 存储范围:1.4E-45 ~ 3.4028235E38
double 存储范围:4.9E-324 ~ 1.7976931348623157E308
char 能够存储一个字符,消耗两个字节的空间
boolean 只能表示 true 和 false
如果我们声明的变量数值大小超出了声明它的数据类型范围,就会出现溢出。
关于浮点数
来看这个程序:
public class Main {
public static void main(String[] args) {
System.out.println(0.1 + 0.2);
}
}
该程序在我的主机输出的结果为:
0.30000000000000004
出现这个结果的原因是因为,计算机中浮点数的存储为近似值。反应到真实项目中,我们要知道,金额是绝对不可以使用浮点数来表示的,因为会出现精度丢失。
一般情况,金额的计算我们会使用 BigDecimal 类型,如代码所示:
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1"); // 一定要使用字符串,或这种形式:BigDecimal.valueOf(0.1);
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b));
}
}
程序输出结果:
0.3
3:类型转换与类型提升类型转换
类型转换原则:
来看示例:
public class Main {
public static void main(String[] args) {
byte a = 1;
int b = a; // 低精度可以直接转换为高精度
int c = 1;
byte d = (byte) c; // 高精度强制转换为低精度,但是要承担溢出风险
}
}
类型提升
什么是类型提升?当不同精度的数据进行计算的时候,得到的结果的类型会提升到参与计算的数据里面最高的精度
示例程序:
public class Main {
public static void main(String[] args) {
short a = 1;
int b = 1;
double c = 0.1;
double d = a + b + c; // short,int,double 这几种类型中, double的精度最高,结果的数据类型即 double
}
}
我们知道,Java 语言中的除法为 “地板除”,譬如:3 / 2 ,该运算结果为:1
我们如果想获得带小数结果,可以使用类型转换与类型提升两种方法:
类型转换:
public static double divide(int a, int b) {
int res = a / b;
return (double) res;
}
类型提升:
public static double divide(int a, int b) {
return (double) a / b; // 先将 a 强制转换为 double 类型,然后用 double 类型数字与int类型数字计算,结果为 double
}
4:基本数据类型对应的装箱类型
基本数据类型与对应的装箱类型:
基本数据类型装箱类型
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
char
Character
boolean
Boolean
为什么要有装箱类型?
我们知道 Java 中只有两种数据类型,第一种是基本数据类型,第二种是引用类型;引用类型声明的是一个对象,保存在堆内存中。
装箱的目的:
装箱将一个基本数据类型包装成一个对象,一个类的对象就可以有很多可以调用的方法,便于我们进行操作
泛型不支持基本类型,例如:List list = new ArrayList();
装箱类型可以指明为 null,我们可以这样声明:Integer i = null;,反之,基本类型是不具有这个特点的
自动装箱与自动拆箱
从 JDK1.5 开始,Java 语言提供了自动装拆箱的机制
public class Main {
public static void main(String[] args) {
int a = 1;
Integer integer = a; // 自动装箱
int b = a; // 自动拆箱
}
}
如程序所示,自动装箱就是自动将基本数据类型转换为包装类型;自动拆箱就是自动将包装类型转换为基本数据类型。
5:== 与 equals 约定在数据类型中的应用
“==” 和 equals 有什么区别?
用一张图可以简要说明 “==” 和 equals 的区别:
我们来看一个示例并进行说明
程序一:
public class Main {
public static void main(String[] args) {
int a = 1000;
int b = 1000;
System.out.println(a == b);
}
}
该程序输出的结果为 true
程序二:
public class Main {
public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b);
}
}
该程序输出的结果为 false
导致两个程序输出结果不同原因是 Integer 是装箱类型,Integer a 和 Integer b 指向的是堆中两块不同的内存。
我们再来看两个程序:
程序一:
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 1;
System.out.println(a == b);
}
}
程序二:
public class Main {
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println(a == b);
}
}
程序一的输出结果为:
true
程序二的输出结果为:
false
为什么会有这样的差异呢?
原因在于java判断变量类型,当我们使用 Integer a = 1; 的方式声明一个变量时,Java 实际上会调用 Integer.valueOf()这个方法。
我们来看下 Integer.valueOf() 这个方法的源代码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
JDK 文档中说明:
也就是说由于 -128 ~ 127 这个区间的值非常常用java判断变量类型, Java 为了减少申请内存的开销使用了 IntegerCache(Integer 常量池)将这些对象储存在常量池中,所以如果使用 Integer 声明的值在 -128 ~ 127 这个区间内的话,就会直接从常量池中取出并返回,于是我们看到程序一输出的结果为 true。
而使用Integer a = new Integer(1); 这种方式声明,则一定会在堆中开辟一块新的内存保存对象,所以程序二的输出结果为 false。
6:数组类型
数组类型是一个非常特殊的类型
数组类型由 JDK 专门使用虚拟机的一些指令来创建