注册

Java中的数据类型

Java是强类型语言

什么是强类型语言?
就是一个变量只能对应一种类型。而不是模棱两可的类型符号。
下面我通过一个例子来解释一下这个现象.

// 此时a为number
var a = 1;
// 此时a为字符串形式的'1'
var a = '1';
复制

可以看到,javascript里面,可以用var来承载各种数据类型,但是在Java,你必须对变量声明具体的数据类型(Java10中也开放了var,目前我们讨论的版本为Java8) 。

8大数据类型

基本类型

存储所需大小

取值范围

int

4字节

-2147483648~2147483647

short

2字节

-32768~32767

long

8字节

-9223372036854775808~9223372036854775807

byte

1字节

-128~127

float

4字节

1.4e-45f~ 3.4028235e+38f

double

8字节

4.9e-324~1.7976931348623157e+308

char

2字节

\u0000~\uFFFF

boolean

根据JVM的编译行为会有不同的结果(1/4)

布尔(boolean)类型的大小没有明确的规定,通常定义为取字面值 “true” 或 “false”

NaN与无穷大

  • NaN

在浮点数值计算中,存在一个NaN来表示该值不是一个数字

/**
* @author jaymin<br>
* 如何表示一个值不是数字
* 2021/3/21 14:54
*/

public class NaNDemo {
public static void main(String[] args) {
Double doubleNaN = new Double(0.0/0.0);
// 一个常数,其值为double类型的非数字(NaN)值
Double nan = Double.NaN;
System.out.println(doubleNaN.isNaN());
System.out.println(nan.isNaN());
}
}
复制
  • 正负无穷大
    private static void isPositiveInfinityAndNegativeInfinity(){
double positiveInfinity = Double.POSITIVE_INFINITY;
double negativeInfinity = Double.NEGATIVE_INFINITY;
System.out.println(positiveInfinity);
System.out.println(negativeInfinity);
}
复制

Result:

Infinity
-Infinity
复制

浮点数存在精度问题

Java中无法用浮点数值来表示分数,因为浮点数值最终采用二进制系统表示。

/**
* @author jaymin<br>
* 浮点数无法表示分数
* @since 2021/3/21 15:07
*/

public class PrecisionDemo {
public static void main(String[] args) {
System.out.println(2.0 - 1.1);
// 如何解决?使用BigDecimal
BigDecimal a = BigDecimal.valueOf(2.0);
BigDecimal b = BigDecimal.valueOf(1.1);
System.out.println(a.subtract(b));
}
}
复制

精度

向上转型和向下强转

  • 向上转型
/**
*
*
* @author jaymin
* @since 2021/3/21 15:40
*/

public class ForcedTransfer {

public static void main(String[] args) {
int n = 123456789;
// 整型向上转换丢失了精度
float f = n;
System.out.println(f);
int n1 = 1;
float f1 = 2.2f;
// 不同类型的数值进行运算,将向上转型
System.out.println(n1 + f1);
}
}
复制

这里我们看到两个现象:

  1. 整型可以赋值给浮点型,但是可能会丢失精度.
  2. 整形和浮点数进行相加,先将整型向上转型为float,再进行float的运算.

层级关系:double>float>long>int

  • 面试官经常问的一个细节

此处能否通过编译?

short s1= 1;
s1 = s1 + 1;
复制

答案是不能的,如果我们对小于 int 的基本数据类型(即 char、byte 或 short)执行任何算术或按位操作,这些值会在执行操作之前类型提升为 int,并且结果值的类型为 int。若想重新使用较小的类型,必须使用强制转换(由于重新分配回一个较小的类型,结果可能会丢失精度).
可以简单理解为: 比int类型数值范围小的数做运算,最终都会提升为int,当然,使用final可以帮助你解决这种问题.

  • 正确示例
short s1= 1;
// 1. 第一个种解决办法
s1 = (short) (s1 + 1);
// 2. 第二种解决办法
s1+=1;
复制
        final short a1 = 1;
final short a2 = 2;
short result = a1 + a2;
复制
  • 向下转型(强制转换)

场景: 在程序中得到了一个浮点数,此时将其转成整形,那么你就可以使用强转.

/**
* 数值之间的强转
*
* @author jaymin
* @since 2021/3/21 15:40
*/

public class ForcedTransfer {

public static void main(String[] args) {
double x = 2021.0321;
// 强转为整型
int integerX = (int) x;
System.out.println(integerX);
x = 2021.8888;
// 四舍五入
int round = (int) Math.round(x);
System.out.println(round);
}
}
复制

Result:

2021  
2022
复制

如果强转的过程中,上层的数据类型范围超出了下层的数据类型范围,那么会进行截断.
可以执行以下程序来验证这个问题.

        long l = Long.MAX_VALUE;
int l1 = (int) l;
System.out.println(l1);
int i = 300;
byte b = (byte) i;
// 128*2 = 256,300-256=44
System.out.println(b);
复制

Reuslt:

-1
44
复制

初始值

基本数据类型都会有默认的初始值.

基本类型

初始值

boolean

false

char

\u0000 (null)

byte

(byte) 0

short

(short) 0

int

0

long

0L

float

0.0f

double

0.0d

在定义对象的时候,如果你使用了基本类型,那么类在初始化后,如果你没有显性地赋值,那么就会为默认值。这在某些场景下是不对的(比如你需要在http中传输id,当对方没有传输id时,你应该报错,但是由于使用了基本的数据类型,id拥有了默认值0,那么此时程序就会发生异常)

定义对象的成员,最好使用包装类型,而不是基础类型.

Integer对象的缓存区

在程序中有些值是需要经常使用的,比如定义枚举时,经常会使用1,2,3作为映射值.Java的语言规范JLS中要求将-128到127的值进行缓存。(高速缓存的大小可以由-XX:AutoBoxCacheMax = <size>选项控制。在VM初始化期间,可以在sun.misc.VM类的私有系统属性中设置并保存java.lang.Integer.IntegerCache.high属性。)

  • 使用==比较Integer可能会出现意想不到的结果
    public static void main(String[] args) {
Integer a1 = Integer.valueOf(127);
Integer a2 = Integer.valueOf(127);
System.out.println(a1==a2);
Integer a3 = Integer.valueOf(128);
Integer a4 = Integer.valueOf(128);
System.out.println(a3==a4);
}
复制

Result:

true
false
复制

解决的办法很简单,使用equals来进行比较即可,Integer内部重写了equals和hashcode.

常用的一些转义字符

在字符串中,如果你想让输出的字符串换行,你就需要用到转义字符

转义字符

Unicode

含义

\b

\u0008

退格

\t

\u0009

制表

\n

\u000a

换行

\r

\u000d

回车

\"

\u0022

双引号

\'

\u0027

单引号

\\

\u005c

反斜杠

\\.

-

.

  • 换行输出字符串
    System.out.println("我马上要换行了\n我是下一行");

0 个评论

要回复文章请先登录注册