基本数据类型,有存放在栈中的,也有存放堆中的,这取决去基本类型声明的位置。

一:在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因

在方法中声明的变量可以是基本类型的变量,也可以是引用类型的变量。     (1)当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在方法栈中     (2)当声明的是引用变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆类存中的。

二:在类中声明的变量是成员变量,也叫全局变量,放在堆中的(因为全局变量不会随着某个方法执行结束而销毁)。

同样在类中声明的变量即可是基本类型的变量 也可是引用类型的变量     (1)当声明的是基本类型的变量其变量名及其值放在堆内存中的     (2)引用类型时,其声明的变量仍然会存储一个内存地址值,该内存地址值指向所引用的对象。引用变量名和对应的对象仍然存储在相应的堆中

比较一下八个基本数据类型的区别吧。

基本数据类型比较

8 bit(位) = 1 Byte (字节)

整 型:byte,short,int,long

浮点型:float,double

逻辑型:boolean

字符型:char

我们先来看几个例子。

  • 奇怪的精度问题
public class demo {    public static void main(String[] arg){        System.out.println(2.00f-1.10f);        System.out.println(2.00-1.10);    }    /*  输出:            0.9            0.8999999999999999    */}

你可能以为程序打印出来的都是0.9,但事实却不是,为什么会出现这种情况呢。

原来2.00和1.10在计算机里存储的时候,需要转换成二进制,浮点型默认是double类型的(即没有加f),从上面的列举的区别表格中知道,float占4个字节32位,double占8个字节64位,而1.10在转换成二进制的时候,是1.000110.......,而double类型表示小数部分只有52位,当向后计算 52位后基数还不为0,那后面的部分只能舍弃,从这里可以看出float、double并不能准确表示每一位小数,对于有的小数只能无限趋向它,所以计算后的结果是0.8999999999999999。

当加上f之后,规定了类型为float精度,并没有double精度那么大,小数部分0.1二进制表示被舍去的比较多。

  • 长整除问题
public class demo {    public static void main(String[] arg){        final long a = 24 * 60 * 60 * 1000 * 1000;        final long b = 24 * 60 * 60 * 1000;        System.out.println(a/b);    }//输出: 5}

1000???错是5,这又是什么情况

24*60*60*1000*1000 的结果计算时为int类型,计算后再转成long型,明显结果超出了int类型的表达范围,在运算的过程中运算结果仍然为int型,超出范围就截取后64位作为运算的结果。因此,我们看到虽然定义了long型变量,但结果仍然是截取后的结果。其实 a = 500654080,b = 86400000 ,得到的结果也就是5。

当我们修改成这样:

public class demo {    public static void main(String[] arg){        final long a = 24l * 60 * 60 * 1000 * 1000;        final long b = 24l * 60 * 60 * 1000;        System.out.println(a/b);    }//输出: 1000}

24后面加上L后,结果就是我们所预期的结果了。

因此,我们中写代码中,如果对精度要求很高的,建议使用BigDecimal来运算,一般用来计算高精度的数据。

为什么需要包装类

因为基本数据类型不是对象,在有些时候使用对象是最方便的,比如List的add(Object e)方法,参数是Object类型,是引用数据类型,那我们想放入基本数据类型怎么办,为了方便操作基本数据类型,所以引入了包装类。

自动装箱和自动拆箱

自动装箱其实就是将基本数据类型转换成包装类,反之自动拆箱就是把包装类转换成基本数据类型。

    public static void main(String[] args) {        Integer i = 10;//自动装箱        int i2 = i;//自动拆箱    }
    public static void main(String[] args) {        int i = 100;        Integer i1 = 100;        Integer i2 = 100;        Integer i3 = 200;        Integer i4 = 200;        System.out.println(i == i1);//  true        System.out.println(i1 == i2);//  true        System.out.println(i3 == i4);// false    }

为什么一个true,一个false呢,我们分析下源码,查看编译后的字节码文件

字节码文件

从字节码文件中,我们可以得知,装箱调用的Integer.valueOf方法,拆箱调用Integer.intValue方法,我们快来看下这两个方法的源码和他的构造函数。

public Integer(int value) {    this.value = value;}public static Integer valueOf(int i) {    if (i >= IntegerCache.low && i <= IntegerCache.high)        return IntegerCache.cache[i + (-IntegerCache.low)];    return new Integer(i);}public int intValue() {    return value;}

i与i1用==比较的时候,会自动将i1自动拆箱,比较的是基本数据类型。

这里没有放出IntegerCache的相关代码,从这个类中可以得知,IntegerCache.low为-128,IntegerCache.high为127,当在这个范围内的基本类型,转换成Integer的时候,就直接从缓存取,所以i1和i2是相等的,但是i3,i4都不在这个范围内,所以都新建了Integer对象,所以不相等。

其实Byte、Short、Integer、Long、Character的valueOf()方法实现机制和Integer类似,但是Float、Double中的valueOf(),永远返回新创建的对象,因为一个范围内的整数是有限的,但是小数却是无限的,无法保存在缓存中,Boolean中只有两个对象,要么是true的Boolean,要么是false的Boolean,只要boolean的值相同,Boolean就相等。

plsql怎么查看存储过程中long变量的值_面试官:详细说下基本数据类型与装箱拆箱的过程...相关推荐

  1. .jar中没有主清单属性_面试官问:为什么SpringBoot的 jar 可以直接运行?

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 来源 | https://urlify.cn/uQvIna SpringBoot提供了一个插件spring-boot-mav ...

  2. md5后得到的32位字符串存储到mysql中太占空间了_面试官:你对MySQL高性能优化有什么规范建议?...

    推荐阅读:吊打面试官!MySQL灵魂100问,你能答出多少? 文章篇幅较长,建议先收藏再找个合适的时间阅读 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用 ...

  3. java中的分页 效率考虑_面试官:数据量很大,分页查询很慢,有什么优化方案?...

    当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点. 下面简单说一下我知道的一些 ...

  4. oracle的存储过程 替换,为什么在存储过程中,变量替换无法使用索引?

    CREATE OR REPLACE PROCEDURE ss(eff_day VARCHAR2) -- eff_day 统计日期,格式为 'yyyymmdd' AS v_year        INT ...

  5. matlab中怎么查看变量,Matlab 查看内存中的变量,清空屏幕等命令

    Matlab 查看内存中的变量,清空屏幕等命令 该文章讲述了Matlab 查看内存中的变量,清空屏幕等命令. 1. 查看内存中的变量 who whos 2. clc 清空屏幕 3. clf 清空当前的 ...

  6. mysql存储过程变量定义_存储过程中MySQL变量定义和赋值

    MySQL变量定义和赋值是我们经常会遇到的问题,下面就为您接受如何在存储过程中MySQL变量定义和赋值,希望对您学习MySQL变量定义方面能有所启迪. 一.MySQL变量的定义 mysql变量定义用d ...

  7. sql动态sql给变量复值_在动态SQL中使用变量

    sql动态sql给变量复值 Before we delve into these SQL concepts, note that I like to do all my development in ...

  8. Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)之二——只改变第一出现的那一行

    一.背景 在之前的文章中有介绍过<Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)> 但是这种方法存在一定的问题,就是假如某个变量在一个文件中出现两次,却只想更改 ...

  9. Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)

    背景 项目初期,创业初期,对于部署还停留在比较简单的时期等等...部署代码需要脚本部署,那么不同环境部署代码的配置也不一样,同一个环境下,多个节点的配置不一样.同一个节点中,多个服务会用到同一个配置项 ...

最新文章

  1. 有无目标的人生差10倍!赶紧和娃把新年计划做起来
  2. 关于量子计算机 (3)
  3. 最常见的显示设置和快捷键
  4. Android开发之自定义view进行旋转动画
  5. Vue CLI 3.0脚手架如何在本地配置mock数据json
  6. 将matlab中数据输出保存为txt或dat格式
  7. c++中基类与派生类中隐含的this指针的分析
  8. 灵活高效,内含SOTA模型,Facebook开源图像分类研究代码库pycls
  9. Android:如何从堆栈中还原ProGuard混淆后的代码
  10. 一次不愉快的面试经历
  11. C++ string 成员函数 length() size() 和 C strlen() 的区别
  12. 2018-09-25 参考博客Hadoop
  13. R语言ETL工程:分组(group_by)
  14. Android源码分析-PackageManagerService(PMS)源码分析(三)- queryIntentActivities函数来查找activity
  15. 信息安全风险评估---矩阵法计算风险
  16. Linux命令之shred命令
  17. 【Redis消息队列实现异步秒杀】--Redis学习笔记08
  18. hbase 常用命令行操作总结
  19. 《天外世界》游戏体验报告
  20. 信用卡如何正确养卡提高额度

热门文章

  1. Screenshot of a full element in Selenium C#
  2. winform实现Echart统计图(基于webBrowser)
  3. 解决服务器上 w3wp.exe 和 sqlservr.exe 的内存占用率居高不下的方案
  4. 在workflow中,无法为实例 ID“...”传递接口类型“...”上的事件“...” 问题的解决方法。...
  5. git 更新远程分支列表(亲测)
  6. php连接mongoDB的几个问题
  7. 记一次MongoDB性能问题(从MySQL迁移到MongoDB)
  8. 九个步骤让你成为PHP专家
  9. Golang中GOPATH在Goland的理解
  10. 反思各种型格人做事方法