Java

[Java]重学Java-Java中的数据类型

2021-03-21  本文已影响0人  AbstractCulture

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来表示该值不是一个数字

/**
 * @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属性。)

    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我是下一行");
上一篇 下一篇

猜你喜欢

热点阅读