A brief introduction of basic types

Two guidelines for basic types:

  • In Java, if you do not specify a type for integers, the default type is int. If you do not specify a type for decimals, the default is double.
  • Base types can be cast automatically from small to large, but cast from large to small.

Number of bytes:

Byte: 1 byte. Char: 2 bytes; Short: 2 bytes; Int: 4 bytes; Long: 8 bytes; Float: 4 bytes; (6 decimal places, the exponent is: 10^-38~10^38; Range:) Double: 8 bytes;

Char: Java uses “\u four hexadecimal digits (even if \u appears in comments, an error will be reported if it is not followed by four hexadecimal digits)” to convert a character to the corresponding Unicode encoding; It can also be assigned with characters such as char c=”\u0000″, the default initialization value of char, and unicode null characters

Suffixes for basic types:

Long: l or l float: f or f; Double: d or d

Type conversion

As mentioned earlier, a cast is required for a type to go from large to small. But this does not mean that users need to cast manually — that is, implicitly. Implicit conversions are defined by the fact that the compiler does the casting without requiring the user to write the casting code. The first two dots below refer to special implicit type conversions.

The conversions discussed in this section do not cover conversions from small to large, but cover other types of conversions that can be more confusing

1. A literal of type int is converted to a variable type lower than type int

Literal constants are the values themselves, such as 5, 7, “aa”, and so on. Let’s start with an example:

public static void main(String[] args) { int a = 8; Byte b = 9; Char c = 9+5; Short s = (short) (c+10); // A variable expression that requires an explicit cast}Copy the code

The code above is compiled and correct. B is a byte type, but b=9 does not require an explicit manual cast because 9 is a literal constant and is done automatically by the JVM. Let’s look again at c=9+5, c is a char, 9+5 produces an int, but we don’t need to explicitly cast it manually. This is because 9+5 is a constant expression, so it is already evaluated by the compiler at compile time. In the same way, short s = (short) (c+10); The expression cannot be cast implicitly because it is not a constant expression, contains variables, and can only be cast at run time.

Limits on implicit conversions of literal constants:

  • A manual cast occurs when the size of an integer literal constant exceeds what the target type can represent.
byte b = 128; Byte c = (byte)128; byte c = (byte)128; // The compiler passesCopy the code
  • When passing parameters, an explicit cast must be performed to specify the type to be cast

The compiler requires implicit conversions to avoid method overloading and automatic conversion of small types to large types.

public static void main(String[] args) { shortMethod(8); // Compiler error shortMethod((short)8); // Compile through longMethod(8); } public static void shortMethod(short c){system.out.println (c); } public static void longMethod(short l){ System.out.println(l); }Copy the code
  • Special cases of the char type: more on this below

2. Implicit conversions of compound operators

The compound operators (+=, -=, *=, /=, %=) automatically cast the type of an expression on the right to the type on the left

public static void main(String[] args) {
    int a = 8;  
    short s = 5; 
    s += a;
    s += a+5;   
}
Copy the code

A and s + s + = = a + 5; Expression evaluates to int, but does not require a manual cast. In fact, if you decompile this code into the class file, you’ll find that s+=a; Is actually handled by the compiler

s=(short)(s+a)
Copy the code

That is, for all implicit conversions of compound operations, the compiler automatically adds the conversion code.

Therefore, there are no restrictions on implicit conversions of compound operators because the former can only occur during compiler time, as opposed to implicit conversions of literal constants that the compiler actually completes.

3. Special char types

The char type is a special presence in the base class. This particularity is that the CHAR type is an unsigned type, so the char type is not a relationship between a subset and a parent set to other primitive types (all of which are signed types). That is, conversions between char and byte and short require explicit casts (small types automatically fail to convert to large types).

Also, because char is an unsigned type, the limitations on implicit conversions of literal constants include not only that literal constants cannot be more than two bytes in size, but also that literal constants cannot be negative

byte b = 2; char c = 2; // Compile through c = 100000000000; // d = (char)-100; // d = (char)-100; Char f = (char)b; F = b; f = b; Int I = c; Short s = (short) c; // If the compiler passes, it must be cast explicitlyCopy the code

Char is an unsigned type. This unsigned type is also reflected when cast to int. In other words, char is also expanded unsigned, with the extension 0. Let’s look at an example:

public static void main(String[] args) {
    short s = -5;
    char c = (char)s; 
    System.out.println(c==s);  //false
    System.out.println("(int)c = "+(int)c); // Convert to int 65531 system.out.println ("(short)c = "+(short)c); //-5
    System.out.println("(int)s = "+(int)s); / / - 5}Copy the code

Running results:

False (int)c = 65531 (short) C = -5 (int)s = -5

From the above results, we can see that c of char and S of short actually store the same bytecode content, but since the former is unsigned, the result of extending to int is 65531 instead of -5. The == operator compares values that they extend to int, hence fasle.

Conversions to char can be summarized as follows:

  • Conversions of char to byte and short require explicit strong conversions.
  • For negative values, an explicit cast is required, especially in implicit conversions of literal constants.
  • The conversion of char to int and long complies with the rule of converting a small type to a large type, that is, no casting is required.

4. Type of operation result

In Java, the type of the result of an operation is equal to the highest type in the expression, as in:

char cc = 5;
floatDd = 0.6 f + cc; // The highest type isfloat, the result of the operation isfloat
float ee = (float) (0.6 d + cc); Double int aa = 5+cc; // The highest type is int, and the result is intCopy the code

However, for operations whose highest type is byte, short, or char, the result is not the highest type, but an int. In the following example, the highest type of c and D operations is char, but the result is int, so a cast is required.

byte b = 2; char a = 5; char c = (char) (a+b); Int e = a+b; int e = a+b; Int char d = (char) (a+c); Char +char, short s1 = 5; short s2 = 6; short s3 =(short)s1+s2;Copy the code

To sum up, the types of Java results have two properties:

  • The result of the operation must be of type int or above.
  • The result of an operation of the highest type less than int is int. Otherwise, the result is the same as the highest type in the expression.

Floating point types

1. Introduction to floating point types

As we all know, there is no casting required to convert long to float, which means that compared to FLAot, long is a small type with a smaller storage range. However, flaot takes up only 4 bytes, while long takes up 8 bytes, and long has more storage space than float. We’ll look at what’s going on here.

Floating point numbers use IEEE (Institute of Electrical and Electronics Engineers) format. Floating-point types are represented by sign bits, exponents, significant bits (mantissa). Notice that the mantissa is the highest

In Java, float and double are structured as follows:

| | operator class type, an effective bit-field | | | refers to the number of domain | – | – | – | | float | 1 | 8 | 23 | | double | 1 | 11 | 52 |

Sign bit: 0 is positive, 1 is negative; Index field: unsigned, float offset is 127, double significant bit field: unsigned;

2. Two caveats to floating point types

1) The value of the stored decimal may be a fuzzy value

Public static void main(String[] args) {double d1 = 0.1; Double d2 = 0.2; System. The out. Println (d1 and d2 = = 0.3); System.out.println(d1+d2); }Copy the code

Running results:

False 0.30000000000000004

This calculation is not a mistake. This is because 0.3, which cannot be accurately stored in binary, is an infinite loop value, similar to 1/3 in base 10. Not just 0.3, many decimal cannot be accurately expressed with floating point, this is determined by the fractional decimal to binary algorithm, the decimal system and with fractions, to take 2, know the final result for the integer is the final binary values, but it may be how also can not get an integer, so finally the result may be an infinite value, Floating point can’t be represented

But for integers, up to the valid range of floating-point numbers, they are exact. Similarly, it is also due to the conversion algorithm: the decimal integer into binary algorithm is constantly taking the remainder of 2, so there is no infinite value;

2) The significant bits and precision of floating point numbers

Floating point can represent a limited number of significant bits, so even integers, as long as more than the significant number, can only store similar values, that is, the value of the least significant bit will be lost, resulting in precision loss. The binary significant bits of float are 24 bits, corresponding to 7 to 8 decimal digits. The binary system contains 53 digits of the double type, corresponding to 10 to 11 digits of the decimal system.

Double and float have a wider range than int and long, and floating-point types are large. However, it is not a perfect surface shaping, and the loss of precision of floating-point types can cause problems.

public static void main(String[] args) {
    int a = 3000000;
    int b = 30000000;
    float f1 = a;
    float f2 = b;
    System.out.println("3000000 = = 3000001"+(f1==f1+1));
    System.out.println("30000000 = = 30000001"+(f2==f2+1));
    
    System.out.println("3000000 valid binary digits:"+ Integer.toBinaryString(a).length());
    System.out.println("30000000 valid binary bits:"+ Integer.toBinaryString(b).length());
}
Copy the code

Running results:

3000000 == 3000001 False 30000000 == 30000001 True Valid binary digits of the 3000000:22 Valid binary digits of the 30000000:25

The above example is a good example of what happens when you lose precision: the comparison of 30000000==30000001 is true. The reason for this is that 30000000 has 25 significant bits, exceeding the 24 significant bits that float can represent, and the last bit is omitted, so that the last one is omitted, so that 30000000 has the same floating-point representation before and after the increment.

Of course, ** is not beyond the floating point significant bits can not be accurately represented, in fact, mainly depends on the “gap” between the highest significant bits and the lowest non-zero significant bits, if the gap is within the floating point significant bits, naturally can be accurately represented, because the low significant bits are 0, naturally does not matter. ** The above example would not have lost precision if it had used a double, since double has precision of 52 bits.

3) Solve the problem of floating point precision loss

Floating-point types can be a pain in the ass, so floats and doubles are generally not used in programs to store large data. And commercial calculations often require accuracy. There is a sentence in Effactive Java:

Float and double are primarily designed for scientific and engineering computation

The JDK provides us with two high-precision large number manipulation classes: BigInteger and BigDecimal.

Reference: http://www.cnblogs.com/jinggod/p/8424583.html

If there are any improper articles, please correct them. You can also pay attention to my wechat public number: Learn Java well and get high quality resources.