Java 从int到byte的有损转换?

Java 从int到byte的有损转换?,java,encryption,Java,Encryption,我的简单加密算法我正在做的一个练习是给我一个从int到byte的可能的有损转换?但是我不知道为什么它会给我这个错误有什么想法吗 public class Rot13Crypt extends CryptStream { public Rot13Crypt(StreamPair theStreams) { super(theStreams); } protected byte [] cryptData(byte [] data, int len)

我的简单加密算法我正在做的一个练习是给我一个从int到byte的可能的有损转换?但是我不知道为什么它会给我这个错误有什么想法吗

public class Rot13Crypt extends CryptStream
{
    public Rot13Crypt(StreamPair theStreams)
    {
        super(theStreams);
    }
    protected byte [] cryptData(byte [] data, int len)
    {
        byte [] cryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            cryptedByte[i] = (data[i] + 13) % 256;
        }
        return cryptedByte;
    }
    protected byte [] decryptData(byte [] data, int len)
    {
        byte [] decryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            decryptedByte[i] = (data[i] * 256) - 13;
        }
        return decryptedByte;
    }
}
public类Rot13Crypt扩展了CryptStream
{
公共ROT13密码(流对流)
{
超级(theStreams);
}
受保护的字节[]加密数据(字节[]数据,整数长度)
{
byte[]cryptedByte=新字节[len];
对于(int i=0;i
一个字节有2^8=256个唯一状态,因此它能代表的最大范围是-128到127

所以假设

 decryptedByte[i] = (data[i] * 256) - 13;

data[i]
值大于
1
将导致该值溢出一个字节的最大值

字节大小为8位,整数大小为32位。因此,执行此转换可能会丢失一些信息

字节数据类型是一个8位有符号2的补码整数。 int数据类型是一个32位有符号2的补码整数

无法将整数放入字节。因此,在精度上的损失。 我希望这是清楚的


示例引用是

它给出了错误消息,因为您试图将int值表达式的值赋给
字节
。这是一个潜在的有损操作:凭直觉,您无法将所有可能的
int
值放入
字节中

Java语言要求在将int值表达式赋给
字节时使用
(byte)
强制转换

您可以在两个地方执行此操作:

   cryptedByte[i] = (data[i] + 13) % 256;

   decryptedByte[i] = (data[i] * 256) - 13;
在第一个表达式中,表达式的值在0到255之间。。。但是Java
byte
值在-128到+127之间

在第二个表达式中,表达式值可能具有范围
(-128*256)-13
到`(+127*256)-13的值。那显然不合适

但这实际上是毫无意义的。Java不允许上述代码的变体,即使您(一个聪明人)可以证明表达式的范围将“适合”到
字节中。JLS禁止这样做。(Java编译器不必是一般定理证明者!!)

只有在表达式是编译时常量表达式且表达式的实际值在
byte
范围内时,才可以将int值表达式分配给
byte
而不进行类型转换

如果您感兴趣,请指定以下状态:

此外,如果表达式是byte、short、char或int类型的常量表达式(§15.28):

  • 如果变量的类型是byte、short或char,并且常量表达式的值可以在变量的类型中表示,则可以使用窄化原语转换
(您需要通过“常量表达式”和“缩小原语转换”来了解规范的含义。我将留给感兴趣的人自己去做。)


那么我会在13和256之前添加一个(字节)强制转换吗

没有。你需要投射整个表情;e、 g

   cryptedByte[i] = (byte) ((data[i] + 13) % 256);

在Java中,
int
类型使用32位编码,
byte
类型使用8位编码。如果将
int
转换为
字节
,如果原始值大于127或小于-128,则可能会丢失信息

整数文本默认为
int
,对
int
的操作返回
int
。因此,
data[i]+13
的结果是
int
(数据[i]+13)%256也一样。当您尝试将该结果存储到
字节(此处为cryptedByte[i])中时,Java会警告您“可能的有损转换”。

您在此处遇到问题

cryptedByte[i] = (data[i] + 13) % 256;
这里呢

decryptedByte[i] = (data[i] * 256) - 13;

256
13
int
类型的文本。当您使用它们和占用较少内存的类型(在本例中为
byte
)执行操作时,会发生类型升级:
数据[i]
被隐式转换(升级)为类型
int
。因此,这两个表达式的计算结果都是
int
。你知道当你把一个int转换成一个字节时会发生什么,对吗?您可能会丢失数据。这是因为
字节
的内存限制小于
int

当每个字节位于一个变量内时,您只需在分配每个字节时进行转换,因此java可以确保所有字节都在-127和127之间,这是ascii范围。以下措施应该有效:

public class Rot13Crypt extends CryptStream
{
    public Rot13Crypt(StreamPair theStreams)
    {
        super(theStreams);
    }
    protected byte [] cryptData(byte [] data, int len)
    {
        byte [] cryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            cryptedByte[i] = (byte) (data[i] + 13) % 256;
        }
        return cryptedByte;
    }
    protected byte [] decryptData(byte [] data, int len)
    {
        byte [] decryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            decryptedByte[i] = (byte) (data[i] * 256) - 13;
        }
        return decryptedByte;
    }
public类Rot13Crypt扩展了CryptStream
{
公共ROT13密码(流对流)
{
超级(theStreams);
}
受保护的字节[]加密数据(字节[]数据,整数长度)
{
byte[]cryptedByte=新字节[len];
对于(int i=0;i

}

请提供完整的编译错误消息/消息,包括行号。
字节在Java中是有符号的-它可以包含-128和127之间的数字,而不是255。那么我是否要在13和256之前添加一个(字节)强制转换?不,只需将整个结果强制转换为byte:cryptedByte[i]=(byte)((数据[i]+13)%256);非常感谢你!现在我很感激你的帮助!非常感谢你!一开始我想不出来