我作为练习做的简单加密算法给了我一个从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;
}
}
答案 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,则可能会丢失信息。
整数文字默认为int
,int
上的操作返回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;
256
和13
是int
类型的文字。当您使用它们并使用占用较少内存的类型(在此示例中为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)