Java随笔:表达式中隐藏的溢出

下面这段代码的输出是什么?

long lvar1 = 24 * 60 * 60 * 1000 * 1000;
long lvar2 = 24 * 60 * 60 * 1000;
System.out.println(lvar1 / lvar2);

一眼看去,应该是1000。

实际的输出是什么呢?5

为什么会得出这样奇怪的结果。我们来反汇编看一下:

执行:javap -c LongOverflowTest.class

结果可以看到:

  public static void main(java.lang.String[]);
    Code:
       0: ldc2_w        #2                  // long 500654080l
       3: lstore_1
       4: ldc2_w        #4                  // long 86400000l
       7: lstore_3

第一个表达式的结果是 500654080,与预期的结果 86400000000不同。

让我们来看看对应的二进制表示:

1010000011101110101110110000000000000
11101110101110110000000000000

是的,这里被截断了。

因为在计算时,没有指定表达式中数值的类型,所以造成都按int类型计算。结果就溢出了。

一种改进的办法:

long lvar3 = 24l * 60 * 60 * 1000 * 1000;

这样计算的结果类型是long,可以得到预期的输出了。

时间: 2024-10-12 08:56:11

Java随笔:表达式中隐藏的溢出的相关文章

Java架构师中的内存溢出和内存泄露是什么?实际操作案例!

JAVA中的内存溢出和内存泄露分别是什么,有什么联系和区别,让我们来看一看. 01 内存泄漏 & 内存溢出 1.内存泄漏(memory leak ) 申请了内存用完了不释放,比如一共有 1024M 的内存,分配了 521M 的内存一直不回收,那么可以用的内存只有 521M 了,仿佛泄露掉了一部分: 通俗一点讲的话,内存泄漏就是[占着茅坑不拉shi]. 2.内存溢出(out of memory) 申请内存时,没有足够的内存可以使用: 通俗一点儿讲,一个厕所就三个坑,有两个站着茅坑不走的(内存泄漏)

Java集合框架中隐藏的设计套路

我们的世界不应该只有"胡萝卜" 进入正题之前容我先扯点别的. 最近突然想到了一个驴子和胡萝卜不得不说的故事.说是一个人坐在驴子背上,用一根长杆绑着一根胡萝卜,然后把胡萝卜悬到驴子的面前,驴子以为只要向前走一步就可以吃到胡萝卜,于是不停地向前走,可是它始终无法吃到这根萝卜. 一千个读者就有一千个哈姆雷特,当然不同的人对这个故事也会有不同的理解.比如我们为了生活拼命地工作,却永远达不到财务自由,我们是不是也像一只忙碌的"驴子"呢? 所以,我们的世界不应该只有"

java、el表达式中保留小数的方法

Java中: import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; public class format { double f = 111231.5585; public void m1() { BigDecimal bg = new BigDecimal(f); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP

No.5 表达式中的陷阱

1. 关于字符串的陷阱 JVM对字符串的处理 String java = new String("Java"); 创建了几个对象? 2个."Java"直接量对应的字符串对象:new String()构造器返回的字符串对象 java.intern() 可以字符串池中的直接量对象. 字符串及基本类型的包装类,Java允许通过直接量的方式来创建对应的Java对象:除此之外,简单的算术表达式.连接计算(编译时可以确定具体值)也可以直接创建对应的Java对象 字符串直接量,J

学习java随笔第八篇:封装、继承、多态

java和c#一样都是面向对象的语言. 面向对象的语言有三大特征:封装.继承.多态 封装 封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别. class Person2 { private String name; public void setName(String name) { this.name=name; } public String getName() { return name; } private String sex; public voi

c++  与  java  中的 继承

C++ 代码: #include <iostream> #include <string> using namespace std; class Parent { public: void fun() {cout<<"Parent fun"<<endl;} void fun(int a) {cout<<"Parent fun int a"<<endl;} void fun(int a, int

Tomcat中JVM内存溢出及合理配置

Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识进行详细介绍. 一.Java JVM内存介绍 JVM管理两种类型的内存,堆和非堆.按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.""在JVM中堆之外的内存称为非堆内存(Non-heap

Java虚拟机学习4、内存溢出

堆溢出 Java堆唯一的作用就是存储对象实例,只要保证不断创建对象并且对象不被回收,那么对象数量达到最大堆容量限制后就会产生内存溢出异常了.所以测试的时候把堆的大小固定住并且让堆不可扩展即可.测试代码如下 1 package com.xrq.test; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * 测试内容:堆溢出 8 * 9 * 虚拟机参数:-Xms20M -Xmx20M -XX:+HeapDumpOn

Java的λ表达式(1)

λ表达式的基本用途 回调与Java8的λ表达式 说明了Java8的λ表达式的基本用途:完成了回调的原意--代码的参数化. 回调:可以简单地说,如果你的方法需要override底层或JDK的某个类的方法,而且你从来没有自己调用过该方法,则该方法(有时候,也指被改写的方法)就是回调.例如 Applet定义的init().start().stop()和destroy(): 图形绘制方法paint(Graphics).update(Graphics)和重载的repaint(): java.lang.Ru