总览

当您在Java中执行一元或二进制操作时,标准行为是使用最宽的操作数(或对byteshortchar使用更宽的操作数)。 这很容易理解,但是如果考虑最佳类型可能会造成混淆。

乘法

当执行乘法运算时,您得到的数值通常比单个数值大得多。 即| a * b | >> | a | 和| a * b | >> | b | 通常是这种情况。 对于小型字体,这可以按预期工作。

考虑以下程序:

public static void main(String[] args) throws IOException {System.out.println(is(Byte.MAX_VALUE * Byte.MAX_VALUE));System.out.println(is(Short.MAX_VALUE * Short.MAX_VALUE));System.out.println(is(Character.MAX_VALUE * Character.MAX_VALUE));System.out.println(is(Integer.MAX_VALUE * Integer.MAX_VALUE));System.out.println(is(Long.MAX_VALUE * Long.MAX_VALUE));
}static String is(byte b) {return "byte: " + b;
}static String is(char ch) {return "char: " + ch;
}static String is(short i) {return "short: " + i;
}static String is(int i) {return "int: " + i;
}static String is(long l) {return "long: " + l;
}

打印:

int: 16129
int: 1073676289
int: -131071
int: 1
long: 1

只有byte * byteshort * short不会溢出,因为它们已被扩展。 char * char即使允许,也不是有意义的操作。 但是int * int确实会溢出,即使我们有一个长类型也可以存储此值而不会溢出。 byteshort都隐式加宽,但不是int 。 应该真正地将long扩展,但是我们没有一个更宽泛的基本类型,这曾经是有意义的,但是如今64位基本类型看起来并不那么长。

在除数可以扩大结果的意义上,除法有些奇怪。 除数比分子宽并不意味着结果会更大(但通常会更小)

System.out.println(is(Byte.MAX_VALUE / (byte) 1));
System.out.println(is(Byte.MAX_VALUE / (short) 1));
System.out.println(is(Byte.MAX_VALUE / (char) 1));
System.out.println(is(Byte.MAX_VALUE / (int) 1));
System.out.println(is(Byte.MAX_VALUE/ (long) 1));

版画

int: 127
int: 127
int: 127
int: 127
long: 127

当你把一个byte/byte你会得到一个int即使你不能得到比一个大的值byte 。 (除非您将Byte.MIN_VALUE除以-1(在这种情况下, short会这样做),并且如果您将byte/long除以byte/long即使值仍然不能大于byte您也会得到long

模量

当执行模数a % b ,结果不能大于b 。 但是模数会扩大结果而不是减少结果。

System.out.println(is(Byte.MAX_VALUE % Byte.MAX_VALUE));
System.out.println(is(Byte.MAX_VALUE % Short.MAX_VALUE));
System.out.println(is(Byte.MAX_VALUE % Character.MAX_VALUE));
System.out.println(is(Byte.MAX_VALUE % Integer.MAX_VALUE));
System.out.println(is(Byte.MAX_VALUE % Long.MAX_VALUE));System.out.println(is(Byte.MAX_VALUE % (byte) 2));
System.out.println(is(Short.MAX_VALUE % (byte) 2));
System.out.println(is(Character.MAX_VALUE % (byte) 2));
System.out.println(is(Integer.MAX_VALUE % (byte) 2));
System.out.println(is(Long.MAX_VALUE % (byte) 2));

版画

int: 0
int: 127
int: 127
int: 127
long: 127
int: 1
int: 1
int: 1
int: 1
long: 1

如果将X乘以一个数,结果将不会比X宽/大,只能变小。 但是,捷豹路虎say必须扩大范围。 如果将X乘以一个byte ,则结果只能在一个byte的范围内。

我还提到了一元运算,也许最简单的是一元减号。

System.out.println(is(-Byte.MIN_VALUE));
System.out.println(is(-Short.MIN_VALUE));
System.out.println(is(-Character.MIN_VALUE));
System.out.println(is(-Integer.MIN_VALUE));
System.out.println(is(-Long.MIN_VALUE));

版画

int: 128
int: 32768
int: 0
int: -2147483648
long: -9223372036854775808

在前三种情况下,类型扩大了。 一个byte可以扩大到short ,但是作为一个int是正确的。 但是对于intlong ,它并没有扩大,您可能会遇到罕见的溢出。

一元奇数是一元加号,它不会更改值(因此无法更改其范围),但可以扩大值。

System.out.println(is(+Byte.MIN_VALUE));
System.out.println(is(+Short.MIN_VALUE));
System.out.println(is(+Character.MIN_VALUE));
System.out.println(is(+Integer.MIN_VALUE));
System.out.println(is(+Long.MIN_VALUE));

版画

int: -128
int: -32768
int: 0
int: -2147483648
long: -9223372036854775808

我们可以解决这个问题吗?

不幸的是没有。 有太多代码依赖于此逻辑。 例如说你写这样的东西。

long i = ...
byte b = ...
long l = i % b + Integer.MAX_VALUE;

如果i%b要从long变为byte ,则此表达式可能会溢出。

结论

Java可以在需要时扩展某些值,但也不能扩展某些int操作,这实际上应该很long 。 即使这可能更合逻辑,也永远不会给出更窄的结果。

我们需要做的是了解边缘情况,尤其是int * int ,并在看到这样的操作时知道自己扩大它们。 例如

long l = (long) a * b;

除非我们确信a * b将适合int值。

翻译自: https://www.javacodegeeks.com/2015/02/inconsistent-operation-widen-rules-java.html

Java中不一致的操作会扩大规则相关推荐

  1. java 不规则 拼图_Java中不一致的操作会扩大规则

    java 不规则 拼图 总览 当您在Java中执行一元或二进制运算时,标准行为是使用最宽的操作数(或对于byte , short和char ,使用更大的操作数). 这很容易理解,但是如果考虑最佳类型可 ...

  2. java中使用lua操作redis

    java中使用lua脚本参见我的上一篇文章 lua基础 本篇简单说下java中使用lua操作redis的示例,如下: 先引入jedis <dependency><groupId> ...

  3. java中四种操作(DOM、SAX、JDOM、DOM4J)xml方式详解与比较(转)

    java中四种操作(DOM.SAX.JDOM.DOM4J)xml方式详解与比较(转) http://wishlife.javaeye.com/blog/181865 posted on 2010-12 ...

  4. 深圳软件测试培训:java中数组的操作

    深圳软件测试培训:java中数组的操作 一.数组最常见的一个操作就是遍历. 因为数组的每个元素都可以通过索引来访问,通过for循环就可以遍历数组. public class M { public st ...

  5. java中的IO操作总结

    java中的IO操作 在java中IO涉及的范围比较大,本文主要针对文件内容的读写 对于文件内容的操作主要分为两大类: 字符流:有两个抽象类 writer Reader 其对应子类FileWriter ...

  6. python字符串赋值与java区别_java和python细节总结和java中string 的+操作

    //JAVA中对arrayList的初始化,能够分配空间,不能之间让一个ArrayList赋值给另外一个ArrayList,这样是引用赋值,当一个改变时候,另外一个也改变 List tmp = new ...

  7. Java中的位移操作 、

    [需求背景]项目需要自定义网络协议,将Beans封装成数据报并发送.为保证数据报头部的长度严格一致,需要将java中的byte.short.int等基本数据类型,通过移位操作来拼装成定长的数据报头部. ...

  8. java 取反 值_java编程 按位取反的问题 java中取反操作是正数

    这个问题涉及到计算机内部的编码. 对于整数,计算机内部用最高位表示符号位,0表示为正,1表示为负. 对于负数,为了便于计算,计算机用补码来表示其值. 已经一个数的补码,要知道其值分两种情况: 1:符号 ...

  9. java中的IO操作总结(一)

    转载:http://www.cnblogs.com/nerxious/archive/2012/12/15/2818848.html    所谓IO,也就是Input与Output的缩写.在java中 ...

最新文章

  1. 返回值与返回引用的问题
  2. React 中的父子组件 兄弟组件传值
  3. 【经典回放】JavaScript学习详细干货笔记之(一)
  4. 网关限流(令牌桶算法)
  5. Android 固定式底部上滑抽屉view
  6. 实践案例丨教你一键构建部署发布前端和Node.js服务
  7. 科研|本科来自普通二本的博士3年迎来2篇Nature,创造校史!
  8. bzoj3594 [Scoi2014]方伯伯的玉米田
  9. 追本溯源:字符串及编码
  10. 南京高中计算机老师,正高级教师、江苏省高中信息技术特级教师——巫雪琴
  11. spring 多租户数据源实现事务一致性
  12. 免费RDP报表工具试用感受
  13. 联想台式主机拆机教程_联想台式电脑主机怎么拆 联想b5040一体机拆机
  14. 从抖音到“奶头乐“,它是如何一步步毁掉我们的?
  15. 基于VQ适量特征的说话人识别
  16. 少儿编程培训 python
  17. RSA 非对称加密算法简述
  18. python读取配置文件 分段_python分割文件的常用方法
  19. 风险评估等级计算机化系统分类,计算机化系统风险评估报告
  20. Multi-modal Dense Video Captioning--论文翻译

热门文章

  1. java实现遍历树形菜单方法——TreeAction实现
  2. idea部署maven+javaweb项目到jboss
  3. tomcatSupplement(1)tomcat启动脚本分析(以Windows平台为例)
  4. 网络——Base64Encode(转:自定义Base64编码器——Base64Encode)
  5. SpringBoot多数据源(主从数据源)配置
  6. web安全测试视频课程专题_有关有效企业测试的视频课程
  7. java初学者指南_Java代理初学者指南
  8. 程序中抛出空指针异常_从Java应用程序中消除空指针异常
  9. commons cli_从Commons CLI迁移到picocli
  10. enumset_枚举集合的EnumSet