首页 > 编程语言 >Java中的无符号类型

Java中的无符号类型

时间:2022-10-08 17:45:46浏览次数:59  
标签:Java 符号 int bytes long 类型 data order

背景

计算机科班出身大多学过离散数学,或者理工类专业也大多学习过 C 或 C++ 语言,从中我们了解到基本类型的整形有 short、int、long 等,还分别有无符号(unsigned)和带符号(signed)的,但是不是所有语言都支持无符号。Java 就是这样一门语言。

但是,在工程实践中,我们难免会有一些场合会用到无符号整型。例如,加密算法等会常进行多轮位运算,这个时候位运算都要求是无符号的。

本文来介绍一下笔者在这块的一些经验,前段时间对一个 C 代码翻译成了 Java 代码,在此过程中,有一点经验总结,记录于此。大家有更好的方法,欢迎留言交流。笔者后续发现新的简洁的方式,也会更新本文。

Java 新版本中会引入无符号,这个不支持无符号的设计,本身是个非常不明智的决定。

使用 unsigned

无符号右移

目前对于无符号的支持,Java 只在位运算的右移支持了一个特殊的符号 »>,支持右移忽略符号位,用 0 填充。但是这个在实践中肯定是远远不够的,很多场景无法满足。

类型升级变相支持

目前想要获得无符号的效果,当前的方法只能进行类型的升级,就是 byte 和 short 转换为 int,int 转换为 long,通过与运算来只保留与原本类型位数一致。因为本身 Java 对各个类型的长度是做了定义的,所以跨平台使用不会有问题。

 // unsigned 注释:java 中没有 unsigned,所以为了实现 unsigned,需要使用比原本类型更大的类型,通过位运算获取其 unsigned 的值
// unsigned byte & short -> int,unsigned int -> long
private static int getUnsignedByte(byte b) {
    return b & 0x0FF;
}

private static int getUnsignedShort(short data) {
    return data & 0x0FFFF;
}

private static long getUnsignedInt(int data) {
    // data & 0xFFFFFFFF 和 data & 0xFFFFFFFFL 结果是不同的,需要注意,有可能与 JDK 版本有关
    return data & 0xFFFFFFFFL;
}

bytes 类型转换

一般来说,无符号的位运算结束后,会将 bytes 转换为 String 或者数字类型,Java 对这类转换的支持还是比较好的,标准库都有相应的 API 支持。

int/long 与 bytes 的互相转换

类型间的转换也属于很常见的操作,C++ 中经常使用这样的技巧来将 4 个 char 的数组变为一个 int。

Java 对这块的支持,还算比较友好,nio 中有 ByteBuffer。需要注意的是,大端(Big-endian)和小端(Little-endian)的选择,这个是与系统强相关的,一般大部分系统都为小端。

short、int 和 long 等类型用类似的 API 即可以完成与 bytes 的互相转换,需要注意三种类型的字节数在各个系统中是固定的,是 Java 语言规范定义的。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

ByteOrder order = ByteOrder.LITTLE_ENDIAN;

// long
long l = 2147483648L;
byte[] bytes = ByteBuffer.allocate(8).order(order).putLong(l).array();
long data = ByteBuffer.wrap(bytes, 0, bytes.length).order(order).getLong();

// int
int i = 123456;
byte[] bytes = ByteBuffer.allocate(4).order(order).putInt(i).array();
int data = ByteBuffer.wrap(bytes, 0, bytes.length).order(order).getInt();

// short

short s = 32767;
byte[] bytes = ByteBuffer.allocate(2).order(order).putShort(s).array();
int data = ByteBuffer.wrap(bytes, 0, bytes.length).order(order).getShort();

String 与 bytes 的互相转换

String 有一个方法叫 getBytes,可以获取 bytes 数组。但是需要注意的是 Java 内部的字符编码是 UTF16 的,而非 UTF8。

还有一点需要注意的是,getBytes 是可以传入字符编码的,这个最好明确指定,否则会用系统默认的,这个可能会在不同环境下行为不一致,导致诡异的错误,较难定位解决。

bytes 转换为 String 也很简单,String 的构造函数直接支持的。

import java.nio.charset.Charset;

Charset charset = Charset.forName("UTF-8");

String data = "abc";
byte[] bytes = data.getBytes(charset);

String newData = new String(bytes, 0, bytes.length, charset);

结尾

以上便是个人的一些经验,笔者通过对上述方法的使用,较为顺利地完成了代码翻译为 Java 的工作,并且测试通过。

希望可以帮助有需要的朋友。欢迎留言讨论。

标签:Java,符号,int,bytes,long,类型,data,order
From: https://www.cnblogs.com/Tiger-Wang-Ai-hu/p/16769683.html

相关文章

  • java异常机制
     java中所有错误的超类为:Throwable。其下有两个子类:Error和Exception。Error的子类描述的都是系统错误,比如虚拟机内存溢出。Exception的子类描述的都是程序,比如空......
  • java_day08
    Java基础Java面向对象面向对象编程(Object-OrientedProgramming,OOP)面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据抽象:把一类事物的公共属性提取......
  • java----模拟幸运抽奖小案例
    模拟幸运抽奖案例:功能:用户注册:注册后随机生成4位数的卡号登录:三次机会,失败一次扣一次机会,机会为0返回主操作幸运抽奖:注册后生成的4位数卡号与随机生成的5个4位数卡号对......
  • 尚硅谷-JavaWeb Day3 jQuery
    1.jQuery介绍:JavaScript和Query,辅助JavaScript 开发的js类库;2.js使用方式①在script标签中,先导入js文件②使用$(function(){....});表示页面......
  • Linux 简单的Java sh脚本启动jar包
    123projectName="你的项目名"45#提醒功能6help(){7echo"help:sh${projectName}.sh[start|stop|restart]"8exit19}1011#判断项......
  • java--IDEA快捷键操作
    1.ctrl+alt+m选择区域代码创建方法的快捷键2.ctrl+shift+-收起类中所有的方法创建对象接收结果快捷键:alt+enter整理代码格式:ctrl+alt+l3.删除一行:ctrl+y4.ctrl+s......
  • 重识Java第九天打卡----面向对象进阶5【集合之Set集合、Map集合】
    一、Set集合1.背景Set继承自Collection,和List一样属于单列集合。2.Set的特点Set具体实现类具有以下共同特点:不重复:可以去除重复无索引:没有带索引的方法(因此不能使用普通f......
  • 重识Java第六天打卡----面向对象进阶2【包、权限修饰符、final和static,关键字、常量
    一、包和权限修饰符1.什么是包?包是一种划分类的层次和结构的封装形式,类似于文件管理系统中的文件夹,并且实际也是以文件夹为形式载体的2.包的作用对类文件进行分类管理。给类......
  • Java学习之路:HelloWorld
    2022-10-0816:13:57HelloWorld  1.随便新建一个文件夹,存放代码  2.新建一个Java文件文件后缀名为.javahello.java注意:系统没有显示后缀名时,需要手动打开......
  • js检测数据类型得四种方式
    1.typeof:返回一个字符串,表示操作数的类型。  语法:typeof(变量)//ortypeof变量示例:  console.log(typeof2)//number  console.log(type......