This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Literal Syntax For byte[] arrays using Hex notation..?
I am trying to create a byte array of size '1' that holds the byte 0x0. In Java, can I just do something like this:
byte[] space = new byte[1];
space[0] = 0x0;
Will the hex value 0x0 be converted to its byte rep of 00000000 and store it in space[0]?
Will the hex value 0x0 be converted to its byte rep of 00000000 and store it in space[0]?
In your executing program, there is only one representation of the Java byte value zero - the 8 bit 2's complement representation of the integer zero - 8 zero bits.
It doesn't make any difference whether you express the number literal in your source code as 0 (decimal) or 00 (octal) or 0x0. They all mean exactly the same thing.
So - Yes, your code does what you expect.
A simpler one line version would be:
byte[] space = new byte[] {0};
or
byte[] space = {0};
or even
byte[] space = new byte[1];
(The last one relies on the fact that Java byte arrays are default initialized to all zeros.)
Will the hex value 0x0 be converted to its byte rep of 00000000 and store it in space[0]?
Sort of yes. Technically (i.e. according to the JLS) what happens is this:
0x0 becomes an int literal. (The specific syntax used for the integer literal is actually immaterial at this point ... so long as it is valid.)
The int literal is narrowed using an implicit primitive narrowing conversion to a byte value.
The byte value is used in the initialization of the array.
The implicit narrowing in step 2 is allowed because:
This is in an assignment context.
The value being assigned is a compile time constant expression of an integer type. (A literal is a compile time constant expression.)
The actual value being assigned is in the range of the type it is to be assigned to. (In this case, -128 to +127.)
In layman's terms, the compiler "knows" that there will never be any loss of information in the narrowing conversion.
Yes this will do exactly what you think it should do. Also see this related question.
Related
byte[] ipAddr = new byte[] {(byte) 142, (byte) 250,68,46};
I am getting to know the various java net functions and I have to cast the first two octets to a byte in order for it to compile.
Otherwise I get this error
java: incompatible types: possible lossy conversion from int to byte
Any idea why I have to cast specifically the first octets and not all? Why does java take it as an int instead of a byte?
In java, bytes are 8-bit signed datatypes, so the value ranges from -128 to +127. Your first two values are greater than the maximum so you need to manually allow the conversion (by casting, in your case).
Those two octets just happen to be larger than the maximum value allowed in a byte which is 127 (2^7-1). Any value greater than 127 will have to be cast (or dealt with more carefully) and you'll lose data in a straight cast due to the size difference. See here for more: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html#:~:text=Primitive%20values%20do%20not%20share,value%20of%20127%20(inclusive).
#Dennis is on the right track, but the explanation is a bit more complicated than that.
Normally, an int valued expression cannot be assigned to a byte variable without a cast.
When the int valued expression is a constant expression, AND when the value of the expression is within the range of byte, then the assignment to a byte variable is allowed without a cast.
However, this only applies in assignment contexts, and only for constant expressions that satisfy the JLS definition.
In your example, the integer literals are all constant expressions, but the first two are not in the required range for lossless assignment ot a byte; i.e -128 to +127.
I am currently going through Java I/O tutorial and having hard time understanding the read() method of FileInputStream class. I know that per documantion that read() method reads "byte" of data from stream and returns an integer representing the byte (between 0 and 256) or -1 if it reaches the end of file.
Byte in java has a range between -128 and 127, so, how come when I edit xanadu.txt and add ASCI symbol "ƒ" (which has a decimal value of 131), java does not complain by throwing an error that value 131 is out of range defined by byte (-128 and 127)? When I try to test this using literals I get two different results.
The following works:
byte b = 120;
int c = b;
System.out.println((char)c);
Output: x
But this does NOT work (even though it works when added to xanadu.txt):
byte b = 131;
int c = b;
System.out.println((char)c);
Output: error: incompatible types: possible lossy conversion from int to byte
byte b = 131;
I tried explicitly casting using byte: (how is this possible?)
byte b = (byte)131;
int c = b;
System.out.println((char)c);
Output: テ
I am total newbie when it comes to I/O streams, somebody please help me understand it.
EDIT: Turns out my knowledge on concepts of type casting was lacking, specifically in understanding the difference between "Widening" and "Narrowing". Reading up more about these concepts helped me understand why explicit (aka narrowing) casting works.
Allow me to explain: Look at the 3rd code block where I am explicitly casting the literal '131' to type of byte. If we are to convert the literal 131 into binary form of 32-bit signed 2's complement integer, we will get 00000000 00000000 00000000 10000011 which is 32-bits or 4 bytes. Recall that Java data type 'byte' can only hold 8-bit signed 2's complement integer, so, 131 is out of range and thus we get error "possible lossy conversion from int to byte". But, when we explicitly cast it to byte, we are 'chopping off' or correct term would be 'narrowing' the binary down to 8 bit integer. So, when we do that, then the resulting binary is 10000011 which is -125 in decimal value. Since -125 is in range of -128 and 127, byte has no issues accepting and storing it. Now when I try to story the value of byte in int c, implicit or "widening" casting takes place, where -125 in binary form of 8-bit 10000011 is converted into equivalent -125 in binary form of 32-bit 11111111 11111111 11111111 10000011. Finally, system.out is trying to output the value of (char)c which is another explicit or "narrowing" casting where its trying to shrink from 32-bit signed to 16-bit unsigned. When casting is complete, we get 11111111 10000011 in binary form. Now, when this binary is converted into character form by java, it returns テ.
I can conclude by saying that it helps converting everything into binary form and go from there. But make sure you understand encoding and 2's complement
I don't know where you got the value 131 from, but as far as I am concerned, LATIN SMALL LETTER F WITH HOOK (ƒ) is not in the original ASCII character set, but in extended ASCII, with a decimal value of 159. See here. It is also encoded in UTF-16 (how Java chars are encoded) as hex 192 (decimal value 402).
First, ensure that your text files are encoded in extended ASCII, and not UTF-8 (which is the most likely encoding). Then you can use a FileInputStream to read the file, and you will get 159.
Note that 159 is outside the range of the the Java byte type. This is fine, because read returns an int. If the text file is encoded in UTF-8 however, ƒ is encoded in 2 bytes, so read will be reading one byte at a time.
Your second code block doesn't work because as you said, byte goes from -128 to 127, so 131 obviously doesn't fit.
Your third code block forces 131 into a byte, which causes overflow and the value "wraps back around" to -125. b and c are both -125. When you cast this to a char it becomes 65411 because this conversion involves padding the whole number to 16-bits first, then treating it as an unsigned integer.
The reason why this all works when you use FileInputStream.read instead of doing these conversions yourself, is because read actually returns an int, not a byte. It's just that the int it returns will always be in the range -1 ~ 255. This is why we say "read returns a byte", but its actual return type is int.
byte b = 131; // this is 8 bits type, but >8 bits value
int c = b; // this is 32 bits type
System.out.println((char)c); // this is 16 bits type
Output: error: incompatible types: possible lossy conversion from int to byte
byte b = 131;
The two-complement encoding of 131 is:
2^7+2^1+2^0
^^^
sign bit
131 won't fit in a signed byte without an overflow in the two complement representation that is used for signed types. The highest bit=sign bit is set which gets extended when casting from byte to int.
The Java compiler notices that 131 won't fit properly in a byte which leads to the error.
This is my Example code
class Example{
public static void main(String args[]){
short s = 100;
byte b = s; // this is compile time error because of no casting
byte z = (short)25.12; // why this happens
System.out.println(z);
System.out.println(((Object)z).getClass());
}
}
please forgive for me as i just begin to learn java.
can you please tell me this problem in technically.
Your this line byte b = s; gives error because you can't assign bigger data type short(2 bytes) to smaller data type byte(1 byte). That is why it is giving you compile time error.
Now coming to this line byte z = (short)25.12; lets break it down. 25.2 is by default double but when you typecast it using (short) it becomes 25 which is an integral literal. Now compiler will check whether 25 can be stored in byte or not. And since 5 is between -128 and 127 i.e. the range of byte it won't give any compile time error. But if you give any value out of the range of byte it will give error. Eg: byte z = (short)128.12;
The compiler doesn’t run your source code or analyze its logic. The compiler merely creates bytecode from each line of your source code.
When the compiler sees byte b = s;, it just tries to generate code that assigns the value of b. It doesn’t look back through your code to see what other instructions may have affected the value of s.
It only knows that on that line of code, you are trying to set an 8-bit value (a byte) to an unknown 16-bit value (a short). When the compiler is looking at this line of code, it does not consider any previous lines, so it doesn’t care about the prior assignment; it treats s as an unknown 16-bit value. That unknown value might or might not be something that fits in 8 bits.
On the other hand, byte z = (short)25.12; is safe because the compiler doesn’t need to look at any other instructions to know that 25 can fit into 8 bits. It doesn’t matter that you have cast it to a short. What matters is that implicitly casting it to byte will not lose any information.
This would be true for (int) 25 as well. In all cases, 25 will fit in 8 bits without losing information.
Typecasting a bigger datatype to a smaller one is not implicit because it can result in an incorrect conversion (loss of data).
byte b = s;
That's why the above line wont't compile because s is of type short (2 bytes) and b is of type byte (1 byte). Hence you need to typecast it explicitly
byte b = (byte)s;
Take a look this article: https://www.javatpoint.com/java-data-types
You getting errors, because:
short takes 16 bit(2 byte)
byte takes 8 bit (1 byte)
You can't put 16 bits, in to 8 bits.
I been reading about encoding Unicode Java 9 compact Strings in the last two days i am getting quite well. But there is something that i dont understand.
About byte data type
1). Is a 8-bit storage ranges from -128 to 127
Questions
1). Why Java didn't implement it like char unsigned 16 bits? i mean it would be in a range of 0.256 because from 0 to 127 only can i hold a Ascii value but what would happen if i set the value 200 a extended ascii would overflow to -56.
2). Does the negative value mean something i mean i have try a simple example using Java 11
final char value = (char)200;//in byte would overflow
final String stringValue = new String(new char[]{value});
System.out.println(stringValue);//THE SAME VALUE OF JAVA 8
I have checked the String.value variable and i see a byte array of
System.out.println(value[0]);//-56
The same questions like before arise does the -56 mean something i mean the (negative value) in other languages this overflow is detected to return to the value 200? How can Java know that -56 value is the same as 200 in char.
I have try hardest examples like codepoint 128048 and i see in String.value variable a array of bytes like this.
0 = 61
1 = -40
2 = 48
3 = -36
I know this codepoint takes 4 bytes but i get it how is transformed char[] to byte[] but i dont know how String handle this byte[] data.
Sorry if this question is simple and sorry any typing english is not my natural language thanks a lot.
Why Java didn't implement it like char unsigned 16 bits? i mean it would be in a range of 0.256 because from 0 to 127 only can i hold a Ascii value but what would happen if i set the value 200 a extended ascii would overflow to -56.
Java’s primitive data types were settled with Java 1.0 a quarter century ago. The compact strings were introduced in Java 9, less than two years ago. This new feature, which is merely an implementation detail, did not justify fundamental changes at Java’s type system.
Besides that, you are looking at one interpretation of the data stored in a byte. For the sake of representing iso-latin-1 units, it is entirely irrelevant whether interpreting the same data as Java’s built-in signed byte would result in a positive or negative number.
Likewise Java’s I/O API allows reading a file into a byte[] array and write byte[] arrays back to files and these two operations are already sufficient to copy a file losslessly, regardless of its file format which would be relevant when interpreting its content.
So the following works since Java 1.1:
byte[] bytes = "È".getBytes("iso-8859-1");
System.out.println(bytes[0]);
System.out.println(bytes[0] & 0xff);
-56
200
The two numbers, -56 and 200 are just different interpretations of the bit pattern 11001000 whereas the iso-latin-1 interpretation of a byte containing the bit pattern 11001000 is the character È.
A char value is also just an interpretation of a two byte quantity, i.e. as UTF-16 code unit. Likewise, a char[] array is a sequence of bytes in the computer’s memory with a standard interpretation.
We can also interpret other byte sequences this way.
StringBuilder sb = new StringBuilder().appendCodePoint(128048);
byte[] array = new byte[4];
StandardCharsets.UTF_16LE.newEncoder()
.encode(CharBuffer.wrap(sb), ByteBuffer.wrap(array), true);
System.out.println(Arrays.toString(array));
will print the value you’ve seen, [61, -40, 48, -36].
The advantage of using a byte[] array inside the String class is, that now, the interpretation can be chosen, to use iso-latin-1 when all characters are representable with this encoding or utf-16 otherwise.
The possible numeric interpretations are irrelevant to the string. However, when you ask “How can Java know that -56 value is the same as 200”, you should ask yourself, how does it know that the bit pattern 11001000 of a byte is -56 in the first place?
System.out.println(value[0]);
bears an actually expensive operation, compared to ordinary computer arithmetic, the conversion of a byte (or an int) to a String. This conversion operation is often overlooked as it has been defined as the default way of printing a byte, but is not more natural than a conversion to a String interpreting the value as an unsigned quantity. For further reading, I recommend Two's complement.
This is because not all bytes in a string are interpreted the same. This depends to the string's character encoding.
Example:
if a string is an UTF-8 string, its characters will be 8-bits in size.
in an UTF-16 string, its characters will be 16-bits in size.
etc...
This means, if the string is to be represented as UTF-8, the characters will be made by reading 1 byte at a time; if 16-bits, the characters will made by reading 2 bytes at a time.
Look at this code: a single byte array data is transformed to string using UTF-8 and UTF-16.
byte[] data = new byte[] {97, 98, 99, 100};
System.out.println(new String(data, StandardCharsets.UTF_8));
System.out.println(new String(data, StandardCharsets.UTF_16));
The output of this code is:
abcd // 4 bytes = 4 chars, 1 byte per char
慢捤 // 4 bytes = 2 chars, 2 byte per char
Going back to the question, what motivated the developers to do so is to reduce memory footprint on strings. Not all strings uses all the 16-bits a char offers.
EDIT: Code here
This question already has answers here:
Odd behavior when Java converts int to byte?
(12 answers)
Closed 9 years ago.
I want to know how can i convert an integer to byte theoretically.
I mean i don't want to use a predefined program but i want just to know how can i implement it.
What i know that from -128 to 127 an integer is the same as byte but the problemes is from 128 to 128 to +infinite and from -129 to -infinite.
For example given the following code:
Integer a = 140;//10001100 this is his binary conversion
Byte zz = (byte) a.byteValue();
System.out.println(zz);// result is -116
How that conversion works in java?
Thanks in advance
That value is out of range of the Byte and hence overflows.
Refer JLS 4.2.1:
The values of the integral types are integers in the following ranges:
For byte, from -128 to 127, inclusive
A byte is 8 bits , the most significant bit specifies the sign of the number and are are encoded in two's complement.
Read this wonderful SO answer for more.
when you are narrowing a primitive, you must explicitly make a cast - so you acknowledge a possible loss of data.
There is no loss if value is within the -128...127 byte value range
Byte value binary representation will not change, it will still be 10001100 but it will be interpreted differently, since byte is a signed type in two's complement representation http://en.wikipedia.org/wiki/Twos_complement and since bit 7 is set it means that now it's a negative number -116
You can not convert value grate than 127 into byte as it do not have place to store it. As 140 in binary is 10001100 it mean that you need a type that store at lest 8 bits. A byte store 8 bits but one of then is reserved for sign. So you can not fit it into it. You can use short witch store 16 bits (15 and 1 for sign).
The zero in different types expressed in binary;
byte b = 0b000_0000;
short s = 0b000_0000_0000_0000;
int i = 0b000_0000_0000_0000_0000_0000_0000_0000;
If you try to declare something like:
byte b = 0b1000_1100;
The compiler will tall you Type mismatch: cannot convert from int to byte.