Java中的初级数值类型

Java是静态类型语言, 所有的变量必须先声明再使用. 其初级类型一共8种:

  • boolean: 数据只包含1bit信息, 但是占空间为8-bit, 默认值为false
  • byte: 8-bit 带符号补码型整数, 取值 -128 ~ 127. 使用于一些对内存空间敏感的大型数组.
  • char: 16-bit单Unicode字符, 最小值也是默认值, 为'\u0000'(或0), 最大值为'\uFFFF'(或65,535).
  • short: 16-bit 带符号补码型整数, 取值 -32,768 ~ 32,767, 用途同上
  • int: 32-bit 带符号补码型整数, 取值 -231 ~ 231 - 1,  这个值是 2,147,483,648(约21.4亿). 自Java8开始, 可以使用int类型来表示一个无符号32-bit整数, 表示 0 ~ 232 的数值, 具体实现在Integer类中.
  • long: 64-bit 带符号补码型整数, 取值 -263 ~ 263 - 1, 自Java8开始, 也可以通过long类型表示一个无符号64-bit整数, 具体实现在Long类中.
  • float: 单精度32-bit IEEE754浮点数.
  • double: 双精度64-bit IEEE754浮点数.

关于32位JVM和64位JVM

无论是32-bit JVM, 还是 64-bit JVM, 以上数值所占空间都是一样的. 在32位JVM和64位JVM上唯一不同的就是引用(reference)的空间大小. 这是关于32位系统和64位系统的一个误区. 在Oracle Java6 update23以及之后, 对于heap大小在32GB以下的JVM, 默认会使用32-bit的引用. 所以严格来讲, 只有heap在32GB以上的64-bit的JVM, 才会在引用这个类型上有区别.

关于初级数值类型赋值的原子性

对于所有的JVM, 除了long和double, 其他初级数值类型的赋值都是保证原子性的. 在64-bit JVM中, 因为64-bit的引用类型其赋值一定是原子的, 所以对long和double的赋值也应当是原子的.

多线程下的可见度

但即便是保证原子性, 仍然不能保证多线程环境下各线程对数值变化的"可见度", 因为线程在内存中会生成"影子变量", 对一个变量的赋值并不能保证将其写回主内存, 除非在主内存更新时被自动更新. 如果你希望线程间所读取的数值保持一致, 你必须以某种同步壁垒的形式来访问线程间共享的状态. 例如volatile关键字或锁.

Volatile 关键字

可以参考这篇文章, 介绍得非常详细: http://tutorials.jenkov.com/java-concurrency/volatile.html

volatile关键字用于将变量标识为"存储于主内存". 更精确些, 就是每一次读取变量值的时候, 都必须从计算机的主内存中读取, 而不能从CPU的缓存, 每一次写变量值的时候, 也必须写到主内存, 而不是CPU的缓存.

Volatile附带的"变化可见度"特性

  • 如果Thread A 写了一个volatile变量 并且Thread B读取了这个volatile变量, 那么所有在写入这个变量前对A"可见"的变量, 在B读取这个变量之后, "变化"变得对B可见.
  • 如果Thread A读取了一个volatile变量, 那么所有在A读取这个变量之前对A"可见"的变量, 在读取后会从主内存中重新读取.

编译时对volatile的处理, 在JDK5以及之后是不同的, 在JDK4时, 对volatile变量的读写与对其他变量的读写指令, 在编译优化阶段可能会被调换顺序, 在JDK5之后保证了发生在volatile变量之前的读写, 不会被调整到volatile变量的读写之后.

JDK5以及之后的顺序保证(Happens-Before Guarantee)

  • 如果代码中对某个变量的读取和写入发生在对volatile变量的写入之前, 那么编译后这个读写操作保证不会被调整到对volatile的写入之后. 注意这仅仅是保证发生在volatile写入之前的操作不会放到后面, 但是不能保证volatile写入之后的操作不会被放到前面.
  • 如果代码中对某个变量的读取和写入发生在对volatile变量的读取之后, 那么编译后这个读写操作保证不会被调整到对volatile的读取之前. 注意这也不能保证volatile读取之前的操作不会被放到后面.

在有写入的场景下, volatile是不够的

需要用synchronized来保证写入不会互相覆盖, 或者使用AtomLong 或 AtomicReference 这样的原子操作类型数据.

包装类的实例之间比较不能直接用 ==

    public static void main(String[] args) {
// TODO Auto-generated method stub
Integer a = new Integer(1);
Integer b = new Integer(1);
int c=1;
Integer e = 1;
System.out.println("a==b:"+(a==b));
System.out.println("a==c:"+(a==c));
System.out.println("a==e:"+(a==e));
System.out.println("c==e:"+(c==e));
}

结果:
a==b:false
a==c:true
a==e:false
c==e:true

Java 中包装类wrapped type之间以及和primitive type的比较的更多相关文章

  1. Java 中基本类型和字符串之间的转换

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  2. Java学习--Java 中基本类型和字符串之间的转换

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  3. java中Integer 和String 之间的转换

    java中Integer 和String 之间的转换 将数组转换成字符串:char[] array = {'a','b','c','d','e'};String str = new String(ar ...

  4. Java中InputStream和String之间的转化

    https://blog.csdn.net/lmy86263/article/details/60479350 在Java中InputStream和String之间的转化十分普遍,本文主要是总结一下转 ...

  5. Java中字节与对象之间的转换

    近期公司里面用到了消息队列,而正如我们知道的是消息队列之间的是通过二进制形式的.以下就分享一下java中字节与对象之间的转换. 主要是用到了ByteArrayOutputStream和ObjectOu ...

  6. JAVA中list,set,数组之间的转换详解

    JAVA的list,set,数组之间的转换,主要是使用Apache Jakarta Commons Collections,具体的方法如下:import org.apache.commons.coll ...

  7. java中paint repaint update 之间的关系

    最近总结了一下java中的paint,repaint和updata三者之间的关系,首先咱们都知道用paint方法来绘图,用repaint重绘,用update来写双缓冲.但是他们之间是怎么来调用的呢,咱 ...

  8. Java中包装类型和基本类型的使用场景(什么时候使用包装类型)(转)

    说明:最简单的理解,基本类型有默认值,而包装类型初始为null.然后再根据这两个特性进行分业务使用,在阿里巴巴的规范里所有的POJO类必须使用包装类型,而在本地变量推荐使用基本类型. Java语言提供 ...

  9. java中JVM和JMM之间的区别

    一 jvm结构 jvm的内部结构如下图所示,这张图很清楚形象的描绘了整个JVM的内部结构,以及各个部分之间的交互和作用. 1 Class Loader(类加载器)就是将Class文件加载到内存,再说的 ...

随机推荐

  1. 【代码笔记】iOS-3DES+Base64加密解密

    一,工程目录. 二,代码. RootViewController.m #import "RootViewController.h" #import "NSString+T ...

  2. iOS开发之集成百度地图踩过的那些坑(基于 Xcode7.0/iOS9.2)

    本篇分4步讲述如何在项目中集成百度地图: 第一步:创建项目 第二步:利用 cocoaPod 导入百度地图的 SDK(pod 'BaiduMapKit' #百度地图SDK) 第三步:在 pch 文件中导 ...

  3. C++语言-09-多任务

    概述 概念 计算机同时运行多个程序的能力,多任务处理的方法是:运行第一个程序的一段代码,保存工作环境:再运行第二个程序的一段代码,保存工作环境:--恢复第一个程序的工作环境,执行第一个程序的下一段代码 ...

  4. 转:JQuery.Ajax之错误调试帮助信息

    今天发现一篇讲Ajax比较好的文章,汇总下,作为自己的知识储备. 下面是Jquery中AJAX参数详细列表: 参数名 类型 描述 url String (默认: 当前页地址) 发送请求的地址. typ ...

  5. linux下安装opcache扩展

    linux下安装opcache扩展   参考:http://www.php.net/manual/zh/opcache.installation.php 1 2 3 4 5 6 7 wget http ...

  6. AEAI DP开发平台精要

    1 背景概述 相信很多了解数通畅联软件的人对AEAI DP应用开发平台并不陌生,笔者在入职第一天就开始接触AEAI DP,使用AEAI DP开发过AEAI WM.AEAI CRM以及中国XXXX管理系 ...

  7. C#实现函数默认值和C#4.0实现默认值

    static void Main(string[] args) { SayHello(); SayHello("侯志强"); Console.ReadKey(); } C#.0实现 ...

  8. 【译】Java中的枚举

    前言 译文链接:http://www.programcreek.com/2014/01/java-enum-examples/ Java中的枚举跟其它普通类很像,在其内部包含了一堆预先定义好的对象集合 ...

  9. Asp.net MVC Razor模板引擎技巧分享

    Razor是Asp.net MVC中新的默认模板类型, 语法简单易用.这篇文章不涉及Razor的语法,主要介绍Razor的一些在MVC项目中的使用技巧,以及脱离MVC环境下,如何使用Razor. 阅读 ...

  10. Learning The Bash Shell读书笔记(整理)

    最近搞了一本书 Learning Bash Shell,发现有人已经写了阅读笔记,我就在这边整理一下 来自blog:http://blog.sina.com.cn/n4mine Learning Th ...