企业网站建设方案书前言国家世界新闻

当前位置: 首页 > news >正文

企业网站建设方案书前言,国家世界新闻,网站被模仿怎么办,网站建设人力成本费用目录 基本数据类型 基本类型和包装类型的区别#xff1f; 自动装箱与拆箱了解吗?原理是什么#xff1f; 为什么浮点数运算的时候回邮精度丢失的风险#xff1f; 如何解决浮点数运算的精度丢失问题#xff1f; 超过 long 整型的数据应该如何表示#xff1f; 基本数据…目录 基本数据类型 基本类型和包装类型的区别 自动装箱与拆箱了解吗?原理是什么 为什么浮点数运算的时候回邮精度丢失的风险 如何解决浮点数运算的精度丢失问题 超过 long 整型的数据应该如何表示 基本数据类型 Java 中有 8 种基本数据类型分别为 6 种数字类型 4 种整数型byte、short、int、long2 种浮点型float、double1 种字符类型char1 种布尔型boolean。 这 8 种基本数据类型的默认值以及所占空间的大小如下 基本类型位数字节默认值取值范围byte810-128 ~ 127short1620-32768-2^15 ~ 327672^15 - 1int3240-2147483648 ~ 2147483647long6480L-9223372036854775808-2^63 ~ 92233720368547758072^63 -1char162u00000 ~ 655352^16 - 1float3240f1.4E-45 ~ 3.4028235E38double6480d4.9E-324 ~ 1.7976931348623157E308boolean1falsetrue、false 可以看到像 byte、short、int、long能表示的最大正数都减 1 了。这是为什么呢这是因为在二进制补码表示法中最高位是用来表示符号的0 表示正数1 表示负数其余位表示数值部分。所以如果我们要表示最大的正数我们需要把除了最高位之外的所有位都设为 1。如果我们再加 1就会导致溢出变成一个负数。 对于 boolean官方文档未明确定义它依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1 位但是实际中会考虑计算机高效存储因素。 另外Java 的每种基本类型所占存储空间的大小不会像其他大多数语言那样随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是 Java 程序比用其他大多数语言编写的程序更具可移植性的原因之一《Java 编程思想》2.2 节有提到。 注意 Java 里使用 long 类型的数据一定要在数值后面加上 L否则将作为整型解析。Java 里使用 float 类型的数据一定要在数值后面加上 f 或 F否则将无法通过编译。char a hchar :单引号String a hello :双引号。 这八种基本类型都有对应的包装类分别为Byte、Short、Integer、Long、Float、Double、Character、Boolean 。 基本类型和包装类型的区别 用途除了定义一些常量和局部变量之外我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且包装类型可用于泛型而基本类型不可以。存储方式基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中基本数据类型的成员变量未被 static 修饰 存放在 Java 虚拟机的堆中。包装类型属于对象类型我们知道几乎所有对象实例都存在于堆中。占用空间相比于包装类型对象类型 基本数据类型占用的空间往往非常小。默认值成员变量包装类型不赋值就是 null 而基本类型有默认值且不是 null。比较方式对于基本数据类型来说 比较的是值。对于包装数据类型来说 比较的是对象的内存地址。所有整型包装类对象之间值的比较全部使用 equals() 方法。 为什么说是几乎所有对象实例都存在于堆中呢 这是因为 HotSpot 虚拟机引入了 JIT 优化之后会对对象进行逃逸分析如果发现某一个对象并没有逃逸到方法外部那么就可能通过标量替换来实现栈上分配而避免堆上分配内存 ⚠️ 注意基本数据类型存放在栈中是一个常见的误区 基本数据类型的存储位置取决于它们的作用域和声明方式。如果它们是局部变量那么它们会存放在栈中如果它们是成员变量那么它们会存放在堆/方法区/元空间中。 public class Test {// 成员变量存放在堆中int a 10;// 被 static 修饰的成员变量JDK 1.7 及之前位于方法区1.8 后存放于元空间均不存放于堆中。// 变量属于类不属于对象。static int b 20;public void method() {// 局部变量存放在栈中int c 30;static int d 40; // 编译错误不能在方法中使用 static 修饰局部变量} }包装类型的缓存机制了解么 Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。 Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128127] 的相应类型的缓存数据Character 创建了数值在 [0,127] 范围的缓存数据Boolean 直接返回 True or False。 Integer 缓存源码 public static Integer valueOf(int i) {if (i IntegerCache.low i IntegerCache.high)return IntegerCache.cache[i (-IntegerCache.low)];return new Integer(i); } private static class IntegerCache {static final int low -128;static final int high;static {// high value may be configured by propertyint h 127;} }Character缓存源码 public static Character valueOf(char c) {if (c 127) { // must cachereturn CharacterCache.cache[(int)c];}return new Character©; }private static class CharacterCache {private CharacterCache(){}static final Character cache[] new Character[127 1];static {for (int i 0; i cache.length; i)cache[i] new Character((char)i);}}Boolean 缓存源码 public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE); } 如果超出对应范围仍然会去创建新的对象缓存的范围区间的大小只是在性能和资源之间的权衡。 两种浮点数类型的包装类 Float,Double 并没有实现缓存机制。 Integer i1 33; Integer i2 33; System.out.println(i1 i2);// 输出 trueFloat i11 333f; Float i22 333f; System.out.println(i11 i22);// 输出 falseDouble i3 1.2; Double i4 1.2; System.out.println(i3 i4);// 输出 false下面我们来看一个问题下面的代码的输出结果是 true 还是 false 呢 Integer i1 40; Integer i2 new Integer(40); System.out.println(i1i2); Integer i140 这一行代码会发生装箱也就是说这行代码等价于 Integer i1Integer.valueOf(40) 。因此i1 直接使用的是缓存中的对象。而Integer i2 new Integer(40) 会直接创建新的对象。 因此答案是 false 。你答对了吗 记住所有整型包装类对象之间值的比较全部使用 equals 方法比较。 自动装箱与拆箱了解吗?原理是什么 什么是自动拆装箱 装箱将基本类型用它们对应的引用类型包装起来拆箱将包装类型转换为基本数据类型 举例 Integer i 10; //装箱 int n i; //拆箱 上面这两行代码对应的字节码为 L1LINENUMBER 8 L1ALOAD 0BIPUSH 10INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;L2LINENUMBER 9 L2ALOAD 0ALOAD 0GETFIELD AutoBoxTest.i : Ljava/lang/Integer;INVOKEVIRTUAL java/lang/Integer.intValue ()IPUTFIELD AutoBoxTest.n : IRETURN从字节码中我们发现装箱其实就是调用了 包装类的valueOf()方法拆箱其实就是调用了 xxxValue()方法。 因此 Integer i 10 等价于 Integer i Integer.valueOf(10)int n i 等价于 int n i.intValue(); 注意如果频繁拆装箱的话也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。 private static long sum() {// 应该使用 long 而不是 LongLong sum 0L;for (long i 0; i Integer.MAX_VALUE; i)sum i;return sum; }为什么浮点数运算的时候回邮精度丢失的风险 浮点数运算精度丢失代码演示 float a 2.0f - 1.9f; float b 1.8f - 1.7f; System.out.println(a);// 0.100000024 System.out.println(b);// 0.099999905 System.out.println(a b);// false 为什么会出现这个问题呢 这个和计算机保存浮点数的机制有很大关系。我们知道计算机是二进制的而且计算机在表示一个数字时宽度是有限的无限循环的小数存储在计算机时只能被截断所以就会导致小数精度发生损失的情况。这也就是解释了为什么浮点数没有办法用二进制精确表示。 就比如说十进制下的 0.2 就没办法精确转换成二进制小数 // 0.2 转换为二进制数的过程为不断乘以 2直到不存在小数为止 // 在这个计算过程中得到的整数部分从上到下排列就是二进制的结果。 0.2 * 2 0.4 - 0 0.4 * 2 0.8 - 0 0.8 * 2 1.6 - 1 0.6 * 2 1.2 - 1 0.2 * 2 0.4 - 0发生循环 …关于浮点数的更多内容建议看一下计算机系统基础四浮点数这篇文章。 如何解决浮点数运算的精度丢失问题 BigDecimal 可以实现对浮点数的运算不会造成精度丢失。通常情况下大部分需要浮点数精确运算结果的业务场景比如涉及到钱的场景都是通过 BigDecimal 来做的。 BigDecimal a new BigDecimal(1.0); BigDecimal b new BigDecimal(1.00); BigDecimal c new BigDecimal(0.8);BigDecimal x a.subtract©; BigDecimal y b.subtract©;System.out.println(x); /* 0.2 / System.out.println(y); / 0.20 / // 比较内容不是比较值 System.out.println(Objects.equals(x, y)); / false / // 比较值相等用相等compareTo相等返回0 System.out.println(0 x.compareTo(y)); / true */ 关于 BigDecimal 的详细介绍可以看看我写的这篇文章BigDecimal 详解。 超过 long 整型的数据应该如何表示 基本数值类型都有一个表达范围如果超过这个范围就会有数值溢出的风险。 在 Java 中64 位 long 整型是最大的整数类型。 long l Long.MAX_VALUE; System.out.println(l 1); // -9223372036854775808 System.out.println(l 1 Long.MIN_VALUE); // trueBigInteger 内部使用 int[] 数组来存储任意大小的整形数据。 相对于常规整数类型的运算来说BigInteger 运算的效率会相对较低。