从int到byte的有损转换?

时间:2015-02-20 07:13:43

标签: java encryption

我作为练习做的简单加密算法给了我一个从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;
    }
}

7 个答案:

答案 0 :(得分:3)

它正在提供该错误消息,因为您正在尝试将int值表达式的值分配给byte。这是一个潜在的有损操作:直观地说,您无法将所有可能的int值放入byte

当您将一个int值表达式分配给(byte)时,Java语言要求您使用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的值。显然不适合。

但这实际上没有实际意义。即使您(一个聪明的人)可以证明表达式的范围“适合”byte,Java也不允许使用上述代码的变体。 JLS禁止这样做。 (Java编译器不需要是一般定理证明器!!)

情况,其中int值表达式可以在没有类型转换的情况下分配给byte,表达式是编译时常量表达式 AND < / em>表达式的实际值在byte范围内。

如果您感兴趣,请在JLS 15.2 Assignment Contexts中指明:

  

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

     
      
  • 如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
  •   

(你需要通过“常量表达”和“缩小原始转换”来追逐规范的含义。我会留下让感兴趣的人为自己做的事情。)


  

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

不。你需要施放整个表达; e.g。

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

答案 1 :(得分:3)

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

整数文字默认为intint上的操作返回int。因此data[i] + 13的结果是int;同样适用于(data[i] + 13) % 256。当您尝试将该结果存储到byte(此处为cryptedByte [i])时,Java会向您发出有关可能有损转换的警告#34;。

答案 2 :(得分:1)

一个字节有2 ^ 8 = 256个唯一状态,因此它可以表示的最大范围是-128到127.

所以假设在

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

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

答案 3 :(得分:0)

你这里有问题

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

在这里

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

25613int类型的文字。当您使用它们并使用占用较少内存的类型(在此示例中为byte)执行操作时,会发生类型提升data[i] 隐式转换(提升)到int类型。因此,这两个表达式都评估为int。而且你知道将int转换为字节时会发生什么,对吧?您可以丢失数据。这是因为byte限制为内存少于int

答案 4 :(得分:0)

当在变量中分配每个字节时,您只需要进行强制转换,因此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;
    }

}

答案 5 :(得分:-1)

字节的大小为8位,大小为32位。因此,通过此转换可能会丢失一些信息!

答案 6 :(得分:-1)

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

无法将整数拟合为一个字节。因此,精度的损失。 我希望它很清楚。

示例参考是here