Lossy conversion from int to byte?
is my simple encryption algorithm that I am doing as an exercise gives me a possible lossy conversion from int to byte? but i dont know why it is giving me this error any ideas?
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;
}
}
source to share
It throws this error message because you are trying to assign a sign value with an internal value byte
. This is a potentially decreasing operation: intuitively, you cannot put all possible values int
into byte
.
The Java language requires you to use translation (byte)
when you assign an int-value to an expression byte
.
There are two places where you do this:
cryptedByte[i] = (data[i] + 13) % 256; decryptedByte[i] = (data[i] * 256) - 13;
In the first case, the value of the expression is in the range 0 to 255 ... but the Java values byte
are in the range -128 to +127.
In the second case, the values of the expression can range from (-128 * 256) - 13
to `(+127 * 256) - 13. This is clearly not appropriate.
But this is actually a moot point. Java does not allow variations of the above code, even if you (a smart person) can prove that the range of the expression will "match" in byte
. The JLS prohibits this. (The Java compiler doesn't have to be a general theorem proof !!)
The only situation where an int-valued expression can be assigned byte
without using the cast type is when the expression is a compile-time constant expression and the actual value of the expression is in the range byte
.
If you are interested, it is stated in JLS 15.2 Assignment Contexts , which says:
Also, if the expression is a constant expression (§15.28) of type byte, short, char, or int:
- A narrowing primitive conversion can be used if the type of the variable is byte, short, or char, and the value of the constant expression is represented in the type of the variable.
(You have to chase what the spec means "constant expression" and "narrowing primitive transformation". I'll leave that for interested people to do for myself.)
then I would add (byte) casting before 13 and 256?
Nope. You need to pass the entire expression; eg.
cryptedByte[i] = (byte) ((data[i] + 13) % 256);
source to share
In Java, a type int
is encoded using 32 bits and a type byte
using 8 bits. If you convert int
to byte
, you may lose information if your original value is greater than 127 or less than -128.
Integer literal has a default value int
and operations with int
return int
. So the result data[i] + 13
is int
; the same for (data[i] + 13) % 256
. When you try to store this result in byte
(cryptedByte [i] here) Java warns you about a "possible lossy conversion".
source to share
You have problems here.
cryptedByte[i] = (data[i] + 13) % 256;
and here
decryptedByte[i] = (data[i] * 256) - 13;
256
and 13
are type literals int
. When you perform operations on them and on a type that takes up less memory (in this example byte
), the type is promoted: data[i]
implicitly converted (promoted) to the type int
. Thus, both of these expressions are evaluated before int
. And you know what happens when you convert an int to a byte, right? You may lose data. This is because it is byte
limited to less memory than int
.
source to share
You just need to cast when assigning each byte when it is inside a variable, so java can make sure everything is between -127 and 127, which is the ascii range. The following should work:
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;
}
}
source to share