- "Java Interview Guide North" is here! This is a booklet that teaches you how to prepare for interviews more efficiently, covering common eight-part essays (system design, common frameworks, distributed, high concurrency...), high-quality interviews, and more.
- JavaGuide (Java Learning && Interview Guide)
: https://javaguide.cn/- First published at: https://javaguide.cn/java/basis/java-basic-questions-01.html
Hello, my name is Guide. The autumn recruitment is coming, I have refactored and improved the content of JavaGuide, and the official account will synchronize the latest update, hoping to help you.
Basic concepts and common sense
What are the characteristics of Java language?
- easy to learn;
- Object-oriented (encapsulation, inheritance, polymorphism);
- Platform independence (Java virtual machine implements platform independence);
- Support multi-threading (C++ language does not have a built-in multi-threading mechanism, so the multi-threading function of the operating system must be called for multi-threaded programming, while Java language provides multi-threading support);
- reliability;
- safety;
- It supports network programming and is very convenient (the birth of the Java language itself is designed to simplify network programming, so the Java language not only supports network programming but also is very convenient);
- Compilation and interpretation coexist;
🐛 Fix (see: issue#544 ) : Since C++11 (in 2011), C++ has introduced a multi-threading library, which can be used in windows, linux, and macosstd::thread
andstd::async
to create a thread. Reference link: http://www.cplusplus.com/reference/thread/thread/?kw=thread
🌈 Expand it:
The propaganda slogan "Write Once, Run Anywhere" is really classic and has been passed down for many years! So, until today, many people still think that cross-platform is the biggest advantage of the Java language. In fact, cross-platform is not Java's biggest selling point, nor are various new JDK features. At present, the virtualization technology on the market is very mature. For example, you can easily achieve cross-platform through Docker. In my opinion, Java's powerful ecology is!
JVM vs JDK vs JRE
JVM
A Java Virtual Machine (JVM) is a virtual machine that runs Java bytecode. The JVM has specific implementations for different systems (Windows, Linux, macOS) with the aim of using the same bytecode and they will all give the same result. Bytecode and JVM implementations for different systems are the crux of the "compile once, run anywhere" Java language.
JVM is not the only one! As long as the JVM specification is met, each company, organization or individual can develop its own dedicated JVM. That is to say, the HotSpot VM we usually come into contact with is just an implementation of the JVM specification.
In addition to our most commonly used HotSpot VM, there are also JVMs such as J9 VM, Zing VM, and JRockit VM. There is a comparison of common JVMs on Wikipedia: Comparison of Java virtual machines , if you are interested, you can take a look. Also, you can find the JVM specifications for each version of the JDK on the Java SE Specifications .
JDK and JRE
JDK is short for Java Development Kit, which is a full-featured Java SDK. It has everything the JRE has, plus the compiler (javac) and tools (like javadoc and jdb). It can create and compile programs.
JRE is the Java Runtime Environment. It is a collection of everything needed to run a compiled Java program, including the Java Virtual Machine (JVM), Java class libraries, java commands, and other basic building blocks. However, it cannot be used to create new programs.
If you just want to run a Java program, then you only need to install the JRE. If you need to do some Java programming work, then you need to install the JDK. However, this is not absolute. Sometimes, even if you don't plan to do any Java development on your computer, you still need to install the JDK. For example, if you're deploying a Web application using JSPs, you're technically just running a Java program in the application server. So why do you need a JDK? Because the application server converts the JSP to a Java servlet, and the JDK needs to be used to compile the servlet.
What is bytecode? What are the benefits of using bytecode?
In Java, the code that the JVM can understand is called bytecode (that is, a file with the extension .class
), which is not oriented to any specific processor, only to the virtual machine. Java language solves the problem of low execution efficiency of traditional interpreted languages to a certain extent by means of bytecodes, and at the same time retains the portability of interpreted languages. Therefore, the runtime of Java programs is relatively efficient (however, there is still a certain gap with languages such as C++, Rust, and Go), and since bytecodes are not specific to a specific machine, Java programs do not require Recompile to run on computers with many different operating systems.
The process of Java program from source code to running is shown in the following figure:
What we need to pay special attention to is .class->机器码
this step. In this step, the JVM class loader first loads the bytecode file, and then interprets and executes it line by line through the interpreter. The execution speed of this method is relatively slow. Moreover, some methods and code blocks are often called (that is, the so-called hot code), so the JIT (just-in-time compilation) compiler was introduced later, and JIT belongs to runtime compilation. When the JIT compiler completes the first compilation, it will save the machine code corresponding to the bytecode, which can be used directly next time. And we know that the operating efficiency of machine code is definitely higher than that of the Java interpreter. This also explains why we often say that Java is a language where compilation and interpretation coexist .
HotSpot adopts the method of Lazy Evaluation. According to the law of 28, only a small part of the code (hot code) consumes most of the system resources, and this is the part that JIT needs to compile. The JVM collects information every time the code is executed and makes some optimizations accordingly, so the more times it is executed, the faster it will be. JDK 9 introduces a new compilation mode, AOT (Ahead of Time Compilation), which directly compiles bytecode into machine code, thus avoiding the overhead of JIT warm-up and other aspects. JDK supports layered compilation and AOT cooperative use. However, the compilation quality of the AOT compiler is definitely not as good as that of the JIT compiler.
Why is it said that the Java language "compiles and interprets side by side"?
In fact, we have already mentioned this issue when we talked about bytecode. Because it is more important, we will mention it here again.
We can divide high-level programming languages into two types according to the way programs are executed:
- Compiled : A compiled language uses a compiler to translate the source code into machine code that can be executed by the platform at one time. Under normal circumstances, the execution speed of compiled languages is relatively fast, and the development efficiency is relatively low. Common compiled languages are C, C++, Go, Rust, etc.
- Interpreted : An interpreted language will interpret the code into machine code sentence by sentence through the interpreter and then execute it. The development efficiency of interpreted languages is relatively fast, and the execution speed is relatively slow. Common interpreted languages are Python, JavaScript, PHP, etc.
According to Wikipedia:
Just-in -time compilation technology, developed to improve the efficiency of compiled languages, has narrowed the gap between the two languages. This technique combines the advantages of compiled and interpreted languages. Like compiled languages, the program source code is first compiled into bytecode . When the execution period is reached, the bytecode is transliterated and then executed. Java and LLVM are representative products of this technology.
Related reading: Basic Skills | Principle Analysis and Practice of Java Just-In-Time Compiler
Why is it said that the Java language "compiles and interprets side by side"?
This is because the Java language has the characteristics of both a compiled language and an interpreted language. Because Java programs need to be compiled first and then interpreted in two steps, programs written in Java need to be compiled first to generate bytecodes ( .class
files), which must be interpreted by the Java interpreter. to explain the implementation.
Oracle JDK vs OpenJDK
Maybe many people like me have not touched and used OpenJDK before reading this question. So are there major differences between Oracle JDK and OpenJDK? Below, I will answer this question, which has been ignored by many people, through some of the information I have collected.
For Java 7, nothing critical. The OpenJDK project is primarily based on the HotSpot source code donated by Sun. Additionally, OpenJDK was chosen as the reference implementation for Java 7, maintained by Oracle engineers. Regarding the difference between JVM, JDK, JRE and OpenJDK, an Oracle blog post from 2012 has a more detailed answer:
Q: What is the difference between the source code in the OpenJDK repository and the code used to build the Oracle JDK?
A: Very close - our Oracle JDK release build process is based on OpenJDK 7 with only a few additions, such as deployment code, which includes Oracle's Java plugin and implementation of Java WebStart, as well as some closed-source third-party components such as A graphics rasterizer, some open source 3rd party components like Rhino, and bits and pieces like additional documentation or 3rd party fonts. Going forward, our intention is to open source all parts of the Oracle JDK, except for those we consider commercial functionality.
Summary: (Hint: The content in brackets below is supplemented based on the original text. Because the original text is too obscure and difficult to understand, it is re-explained in human words. If you understand the terms inside, you can ignore the content explained in brackets)
- Oracle JDK releases major releases roughly every 6 months (3+ years from JDK 8 LTS release in March 2014 to JDK 9 release in September 2017, so not always 6 months), while OpenJDK releases are released approximately every three months. But it's not fixed, and I don't think it's useful to know this. See: https://blogs.oracle.com/java-platform-group/update-and-faq-on-the-java-se-release-cadence for details.
- OpenJDK is a reference model and is completely open source, while Oracle JDK is an implementation of OpenJDK, which is not completely open source; (personal point of view: As we all know, JDK was originally developed by SUN, and then SUN sold it to Oracle, Oracle is famous for its Oracle database, and Oracle database is closed source. At this time, Oracle does not want to completely open source, but the original SUN company has open sourced JDK again. If Oracle buys it back at this time, it will give him Closed source will inevitably arouse the dissatisfaction of many Java developers, causing everyone to lose confidence in Java. Wouldn't Oracle rot Java in its hands after the acquisition! Then, Oracle thought of a tricky operation, so let's go , I will open source a part of the core code for you to play, and I want to distinguish it from the JDK you made yourself, you call it OpenJDK, I call Oracle JDK, I release mine, you continue to play with yours, if you come up with something fun I will use the Oracle JDK in the follow-up release, killing two birds with one stone!) OpenJDK open source project: https://github.com/openjdk/jdk
- Oracle JDK is more stable than OpenJDK (for sure, Oracle JDK is independently developed by Oracle's internal team, and the release time is not longer than OpenJDK, and the quality is more guaranteed). The code of OpenJDK and Oracle JDK are almost the same (OpenJDK code is derived from Oracle JDK code, which can be understood as a new branch called OpenJDK on the Oracle JDK branch, so most of the code is the same), but Oracle JDK has more More classes and some bug fixes. So if you want to develop enterprise/commercial software, I recommend you to choose Oracle JDK as it is thoroughly tested and stable. In some cases, some people mentioned that using OpenJDK may have encountered many application crashes, however, simply switching to Oracle JDK solved the problem;
- Oracle JDK provides better performance compared to OpenJDK in terms of responsiveness and JVM performance;
- Oracle JDK does not provide long-term support for upcoming releases (it does if it is an LTS long-term support release, such as JDK 8, but not every release is an LTS release), and users must update to the latest version each time to get it Support to get the latest version;
- Oracle JDK is licensed under the BCL/OTN license, while OpenJDK is licensed under the GPL v2 license.
Since Oracle JDK is so good, why even have OpenJDK?
answer:
- OpenJDK is open source. Open source means that you can modify and optimize it according to your own needs. For example, Alibaba developed Dragonwell8 based on OpenJDK: https://github.com/alibaba/dragonwell8
- OpenJDK is commercially free (that's why the JDK installed by default on the yum package manager is OpenJDK and not Oracle JDK). While Oracle JDK is also commercially free (such as JDK 8), not all versions are free.
- OpenJDK is updated more frequently. Oracle JDK generally releases a new version every 6 months, while OpenJDK generally releases a new version every 3 months. (Now you know why Oracle JDK is more stable, test the water in OpenJDK first, and solve most of the problems before releasing it on Oracle JDK)
For these reasons, OpenJDK still needs to exist!
🌈 Expand it:
- BCL agreement (Oracle Binary Code License Agreement): JDK (support for commercial use) can be used, but cannot be modified.
- OTN Agreement (Oracle Technology Network License Agreement): JDK 11 and later releases use this agreement, which can be used privately, but commercial use requires payment.
Related reading👍: "Differences Between Oracle JDK and OpenJDK"
Difference between Java and C++?
I know that many people have never learned C++, but the interviewer just likes to compare our Java and C++! no way! ! ! Even if you haven't learned C++, remember it.
Although both Java and C++ are object-oriented languages that support encapsulation, inheritance and polymorphism, they still have quite a few differences:
- Java does not provide pointers to directly access memory, program memory is more secure
- Java classes are single-inherited, and C++ supports multiple inheritance; although Java classes cannot be multi-inherited, interfaces can be multi-inherited.
- Java has an automatic memory management garbage collection mechanism (GC), which does not require programmers to manually release useless memory.
- C++ supports both method overloading and operator overloading, but Java only supports method overloading (operator overloading adds complexity, which is inconsistent with Java's original design).
- ......
basic grammar
What is the difference between character constants and string constants?
- Form : A character constant is one character enclosed in single quotes, and a string constant is zero or more characters enclosed in double quotes.
- Meaning : A character constant is equivalent to an integer value (ASCII value) and can participate in expression operations; a string constant represents an address value (where the string is stored in memory).
- Occupied memory size : Character constants occupy only 2 bytes; string constants occupy several bytes.
( Note: char
occupies two bytes in Java )
What are the types of annotations?
There are three types of annotations in Java:
- single line comment
- multi-line comment
- Documentation comments.
When we write code, if the amount of code is relatively small, we or other members of the team can easily understand the code, but when the project structure is complicated, we need to use comments. Comments will not be executed (the compiler will erase all comments in the code before compiling the code, and no comments will be retained in the bytecode), which is written by our programmers for ourselves. Comments are your code instructions, which can help People who look at the code quickly understand the logical relationship between the codes. Therefore, it is a very good habit to add comments when writing programs.
The book Clean Code clearly states:
Code comments are not as detailed as possible. In fact, good code itself is a comment. We should try our best to standardize and beautify our code to reduce unnecessary comments.
If the programming language is expressive enough, there is no need for comments, and try to explain it through code.
for example:
Remove the complex comments below, just create a function that does the same thing as the comment says
// check to see if the employee is eligible for full benefits if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
should be replaced with
if (employee.isEligibleForFullBenefits())
What is the difference between an identifier and a keyword?
When we write programs, we need a lot of names for programs, classes, variables, methods, etc., so there are identifiers . In simple terms, an identifier is a name .
There are some identifiers that the Java language has given them special meanings and can only be used in specific places, these special identifiers are keywords . In simple terms, keywords are identifiers that are assigned special meanings . For example, in our daily life, if we want to open a store, we need to give the store a name, and this "name" is called an identifier. But the name of our store can't be called "police station", because the name "police station" has been given special meaning, and "police station" is the keyword in our daily life.
What are the Java language keywords?
Classification | keywords | ||||||
---|---|---|---|---|---|---|---|
Access control | private | protected | public | ||||
Class, method and variable modifiers | abstract | class | extends | final | implements | interface | native |
new | static | strictfp | synchronized | transient | volatile | enum | |
Program control | break | continue | return | do | while | if | else |
for | instanceof | switch | case | default | assert | ||
error handling | try | catch | throw | throws | finally | ||
package related | import | package | |||||
basic type | boolean | byte | char | double | float | int | long |
short | |||||||
variable reference | super | this | void | ||||
reserved word | goto | const |
Tips: All keywords are in lowercase and will be displayed in a special color in the IDE.
default
This keyword is very special. It belongs to program control, class, method and variable modifier, and access control.
- In program control, when nothing matches in
switch
, you can usedefault
to write the default matching case.- In the class, method and variable modifiers, default methods have been introduced since JDK8, and the
default
keyword can be used to define the default implementation of a method.- In access control, if there is no modifier before a method, there will be a modifier
default
by default, but if this modifier is added, an error will be reported.
⚠️ Note: Although true
, false
, and null
look like keywords they are actually literals and you can't use them as identifiers use.
Official documentation: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/\_keywords.html
increment/decrement operator
In the process of writing code, a common situation is that an integer type variable needs to be incremented or decremented by 1. Java provides a special operator for this kind of expression, called the auto-increment operator (++ ) and the decrement operator (--).
The ++ and -- operators can be placed before the variable or after the variable. When the operator is placed before the variable (prefix), it is incremented/decremented first, and then assigned; when the operator is placed after the variable ( suffix), assign first, and then increment/decrement. For example, when b = ++a
, first increment (by adding 1 by itself), and then assign a value (assign to b); when b = a++
, first assign a value (assign b), and then increment (Add 1 to yourself). That is, ++a outputs the value of a+1, and a++ outputs the value of a. A formula is: "Add/subtract the symbol first, and add/subtract the symbol after."
What is the difference between continue, break and return?
In the loop structure, when the loop condition is not satisfied or the number of loops meets the requirements, the loop will end normally. However, sometimes it may be necessary to terminate the loop in advance when a certain condition occurs during the loop, which requires the use of the following keywords:
-
continue
: means to jump out of the current cycle and continue to the next cycle. -
break
: means to jump out of the entire loop body and continue to execute the statement below the loop.
return
is used to jump out of the method and end the operation of the method. return is generally used in two ways:
-
return;
: Use return to end the method execution directly, for methods without a return value function -
return value;
: return a specific value, used for methods with return-value functions
Think about it: What is the result of running the following statement?
public static void main(String[] args) {
boolean flag = false;
for (int i = 0; i <= 3; i++) {
if (i == 0) {
System.out.println("0");
} else if (i == 1) {
System.out.println("1");
continue;
} else if (i == 2) {
System.out.println("2");
flag = true;
} else if (i == 3) {
System.out.println("3");
break;
} else if (i == 4) {
System.out.println("4");
}
System.out.println("xixi");
}
if (flag) {
System.out.println("haha");
return;
}
System.out.println("heihei");
}
operation result:
0
xixi
1
2
xixi
3
haha
method
What is the return value of a method? What types of methods are there?
The return value of the method refers to the result of the execution of the code in a method body obtained by us! (provided that the method is likely to yield results). The function of the return value is to receive the result so that it can be used for other operations!
We can divide methods into the following types according to their return values and parameter types:
1. A method with no parameters and no return value
public void f1() {
//......
}
// 下面这个方法也没有返回值,虽然用到了 return
public void f(int a) {
if (...) {
// 表示结束方法的执行,下方的输出语句不会执行
return;
}
System.out.println(a);
}
2. A method with parameters but no return value
public void f2(Parameter 1, ..., Parameter n) {
//......
}
3. A method with a return value and no parameters
public int f3() {
//......
return x;
}
4. A method with a return value and parameters
public int f4(int a, int b) {
return a * b;
}
Why can't static methods call non-static members?
This needs to be combined with the relevant knowledge of the JVM. The main reasons are as follows:
- Static methods belong to classes, and memory is allocated when the class is loaded, which can be accessed directly through the class name. Non-static members belong to instance objects, which exist only after the object is instantiated, and need to be accessed through the instance object of the class.
- When the non-static member of the class does not exist, the static member already exists. At this time, calling the non-static member that does not exist in the memory is an illegal operation.
What is the difference between a static method and an instance method?
1. Calling method
When calling a static method externally, you can use the method 类名.方法名
, or you can use the method 对象.方法名
, and the instance method only has the latter method. That is, static methods can be called without creating an object .
However, it should be noted that it is generally not recommended to use the 对象.方法名
method to call static methods. This approach is very confusing, static methods do not belong to an object of the class but belong to the class.
Therefore, it is generally recommended to use 类名.方法名
to call static methods.
public class Person {
public void method() {
//......
}
public static void staicMethod(){
//......
}
public static void main(String[] args) {
Person person = new Person();
// 调用实例方法
person.method();
// 调用静态方法
Person.staicMethod()
}
}
2. Are there restrictions on accessing class members?
When a static method accesses members of this class, only static members (ie, static member variables and static methods) are allowed, and instance members (ie, instance member variables and instance methods) are not allowed, while instance methods do not have this restriction.
The difference between overloading and overriding
Overloading is the same method that can be processed differently depending on the input data
Overriding is when the subclass inherits the same method of the parent class, the input data is the same, but when you want to respond differently from the parent class, you have to override the parent class method
overload
Occurs in the same class (or between parent and child classes), the method name must be the same, the parameter type, number, and order are different, and the method return value and access modifier can be different.
The book "Java Core Technology" describes overloading like this:
If multiple methods (such as the constructor of
StringBuilder
) have the same name and different parameters, overloading occurs.StringBuilder sb = new StringBuilder(); StringBuilder sb2 = new StringBuilder("HelloWorld");
The compiler must pick out which method to execute, by matching the parameter types given to each method with the value types used by the particular method invocation. If the compiler cannot find a matching argument, it will generate a compile-time error because there is no match at all, or none is better than the other (this process is called overloading resolution).
Java allows overloading of any method, not just constructor methods.
To sum up: Overloading means that multiple methods with the same name in the same class perform different logical processing according to different parameters.
rewrite
Overriding occurs at runtime, and the subclass rewrites the implementation process of the method that allows access to the parent class.
- The method name and parameter list must be the same, the return value type of the subclass method should be smaller or equal to the return value type of the parent class method, the range of the exception thrown is less than or equal to the parent class, and the range of the access modifier is greater than or equal to the parent class.
- If the parent class method access modifier is
private/final/static
, the subclass cannot override the method, but the method modified bystatic
can be declared again. - Constructor cannot be overridden
To sum up: Overriding is the re-engineering of the method of the parent class by the subclass. The external appearance cannot be changed, but the internal logic can be changed.
difference | overloaded method | Override method |
---|---|---|
range of occurrence | the same class | Subclass |
parameter list | must be modified | must not be modified |
return type | Can be modified | The return value type of the subclass method should be less than or equal to the return value type of the parent class method |
abnormal | Can be modified | The exception class declared by the subclass method should be smaller or equal to the exception class thrown by the superclass method declaration; |
access modifier | Can be modified | Must not do stricter restrictions (can lower restrictions) |
Occurrence stage | compile time | run time |
The rewriting of the method should follow the "two same, two small and one big" (the following is excerpted from "Crazy Java Lectures", issue#892 ):
- "Two identical" means the same method name and the same formal parameter list;
- "Two small" means that the return value type of the subclass method should be smaller or equal to the return value type of the superclass method, and the exception class declared by the subclass method should be smaller or equal than the exception class thrown by the superclass method declaration ;
- "One big" means that the access rights of the subclass method should be greater or equal than the access rights of the superclass method.
⭐️ About the return value type of overriding Here I need to explain more. The above expression is not clear and accurate: if the return type of the method is void and basic data type, the return value cannot be modified when it is overridden. However, if the return value of the method is a reference type, it is possible to return a subclass of the reference type when overriding.
public class Hero {
public String name() {
return "超级英雄";
}
}
public class SuperMan extends Hero{
@Override
public String name() {
return "超人";
}
public Hero hero() {
return new Hero();
}
}
public class SuperSuperMan extends SuperMan {
public String name() {
return "超级超级英雄";
}
@Override
public SuperMan hero() {
return new SuperMan();
}
}
What is a variable length parameter?
Since Java5, Java supports the definition of variable-length parameters. The so-called variable-length parameters allow parameters of indeterminate length to be passed in when calling a method. For example, the following printVariable
method can accept 0 or more parameters.
public static void method1(String... args) {
//......
}
Also, a variadic parameter can only be the last parameter of a function, but it may or may not be preceded by any other parameters.
public static void method2(String arg1, String... args) {
//......
}
What to do when you encounter method overloading? Will the method with fixed or variadic parameters be matched preferentially?
The answer is that methods with fixed parameters will be preferentially matched, because methods with fixed parameters have a higher degree of matching.
Let us prove it with the following example.
/**
* 微信搜 JavaGuide 回复"面试突击"即可免费领取个人原创的 Java 面试手册
*
* @author Guide哥
* @date 2021/12/13 16:52
**/
public class VariableLengthArgument {
public static void printVariable(String... args) {
for (String s : args) {
System.out.println(s);
}
}
public static void printVariable(String arg1, String arg2) {
System.out.println(arg1 + arg2);
}
public static void main(String[] args) {
printVariable("a", "b");
printVariable("a", "b", "c", "d");
}
}
output:
ab
a
b
c
d
In addition, Java's variable parameters will actually be converted into an array after compilation. We can see it by looking at the class
file generated after compilation.
public class VariableLengthArgument {
public static void printVariable(String... args) {
String[] var1 = args;
int var2 = args.length;
for(int var3 = 0; var3 < var2; ++var3) {
String s = var1[var3];
System.out.println(s);
}
}
// ......
}
basic data type
Do you know several basic data types in Java?
There are 8 basic data types in Java, they are:
6 numeric types:
- 4 integer types:
byte
,short
,int
,long
- 2 floating point types:
float
,double
- 4 integer types:
- 1 character type:
char
- 1 boolean:
boolean
.
The default values of these 8 basic data types and the size of the space occupied are as follows:
basic type | number of digits | byte | Defaults | Ranges |
---|---|---|---|---|
byte | 8 | 1 | 0 | -128 ~ 127 |
short | 16 | 2 | 0 | -32768 ~ 32767 |
int | 32 | 4 | 0 | -2147483648 ~ 2147483647 |
long | 64 | 8 | 0L | -9223372036854775808 ~ 9223372036854775807 |
char | 16 | 2 | 'u0000' | 0 ~ 65535 |
float | 32 | 4 | 0f | 1.4E-45 ~ 3.4028235E38 |
double | 64 | 8 | 0d | 4.9E-324 ~ 1.7976931348623157E308 |
boolean | 1 | false | true, false |
For boolean
, the official document is not clearly defined, it depends on the specific implementation of the JVM vendor. The logical understanding is to occupy 1 bit, but in practice, the efficient storage factor of the computer will be considered.
In addition, the size of the storage space occupied by each of Java's basic types does not vary with the hardware architecture of the machine like most other languages. This invariance of storage size is one of the reasons Java programs are more portable than programs written in most other languages (mentioned in Section 2.2 of "Java Programming Ideas").
Notice:
- The data of type
long
used in Java must add L after the value, otherwise it will be parsed as an integer. -
char a = 'h'
char : single quote,String a = "hello"
: double quote.
这八种基本类型都有对应的包装类分别为: Byte
、 Short
、 Integer
、 Long
、 Float
, Double
, Character
, Boolean
.
Difference between primitive type and wrapper type?
- The non-assigned member variable wrapper type is
null
, while the basic type has a default value and is notnull
. - Wrapper types can be used with generics, while primitive types cannot.
- The local variables of the basic data type are stored in the local variable table in the Java virtual machine stack, and the member variables of the basic data type (not modified by
static
) are stored in the heap of the Java virtual machine. Wrapper types are object types, and we know that almost all object instances exist in the heap. - Compared to object types, primitive data types take up very little space.
Why is it said to be almost all object instances? This is because the HotSpot virtual machine will perform escape analysis on objects after JIT optimization is introduced. If it is found that an object does not escape to the outside of the method, it is possible to achieve stack allocation through scalar replacement, and avoid memory allocation on the heap.
⚠️ Note: It is a common misunderstanding that primitive data types are stored on the stack! If the member variable of the basic data type is not modified by static
(it is not recommended to use it, you should use the packaging type corresponding to the basic data type), it will be stored in the heap.
class BasicTypeVar{
private int x;
}
Do you understand the caching mechanism of the packaging type?
Most of the wrapper types for Java primitives use caching mechanisms to improve performance.
Byte
, Short
, Integer
, Long
4 种包装类默认创建了数值[-128,127]的相应类型的缓存数据, Character
在[0,127]范围的缓存数据, Boolean
返回True
or False
。
Integer cache source:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static {
// high value may be configured by property
int h = 127;
}
}
Character
Cache source code:
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
private static class CharacterCache {
private CharacterCache(){}
static final Character cache[] = new Character[127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Character((char)i);
}
}
Boolean
Cache source code:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
If it exceeds the corresponding range, new objects will still be created, and the size of the cached range interval is only a trade-off between performance and resources.
The wrapper classes for the two floating point types Float
, Double
do not implement a caching mechanism.
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true
Float i11 = 333f;
Float i22 = 333f;
System.out.println(i11 == i22);// 输出 false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出 false
Let's take a look at the problem. Is the output of the following code true
or false
?
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);
Integer i1=40
This line of code will be boxed, which means that this line of code is equivalent to Integer i1=Integer.valueOf(40)
. Therefore, i1
uses the object in the cache directly. And Integer i2 = new Integer(40)
will create new objects directly.
So the answer is false
. Did you get it right?
Remember: All comparisons of values between objects of an integer wrapper class use the equals method .
Do you understand autoboxing and unboxing? What is the principle?
What is automatic unboxing?
- Boxing : wrapping primitive types with their corresponding reference types;
- Unboxing : Convert the wrapper type to a primitive data type;
Example:
Integer i = 10; //装箱
int n = i; //拆箱
The bytecode corresponding to the above two lines of code is:
L1
LINENUMBER 8 L1
ALOAD 0
BIPUSH 10
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;
L2
LINENUMBER 9 L2
ALOAD 0
ALOAD 0
GETFIELD AutoBoxTest.i : Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue ()I
PUTFIELD AutoBoxTest.n : I
RETURN
From the bytecode, we found that boxing is actually calling the valueOf()
method of the packaging class, and unboxing is actually calling the xxxValue()
method.
therefore,
-
Integer i = 10
equivalent toInteger i = Integer.valueOf(10)
-
int n = i
equivalent toint n = i.intValue()
;
Note: Frequent unpacking and unpacking can also seriously affect the performance of the system. We should try to avoid unnecessary unboxing operations.
private static long sum() {
// 应该使用 long 而不是 Long
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += i;
return sum;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。