Hello, my name is Guide. The autumn recruitment is coming, I have refactored and improved the content of JavaGuide , and synchronized the latest update, hoping to help you.
The first two articles:
- Java Basics Common Knowledge Points & Interview Questions Summary (Part 1), the latest version in 2022!
- Java basic common knowledge points & interview questions summary (in), the latest version of 2022
abnormal
Java exception class hierarchy diagram overview :
What is the difference between Exception and Error?
In Java, all exceptions have a common ancestor java.lang
package Throwable
class. Throwable
The class has two important subclasses:
-
Exception
: Exceptions that can be handled by the program itself can be caught bycatch
.Exception
can be divided into Checked Exception (checked exception, must be handled) and Unchecked Exception (unchecked exception, can not be handled). -
Error
:Error
is an error that cannot be handled by the program,We can't capture it byCapture viacatch
catch
is not recommended. For example, Java virtual machine running error (Virtual MachineError
), virtual machine memory is not enough error (OutOfMemoryError
), class definition error (NoClassDefFoundError
) and so on. When these exceptions occur, the Java Virtual Machine (JVM) typically chooses to terminate the thread.
What is the difference between Checked Exception and Unchecked Exception?
Checked Exception is a checked exception. During the compilation process of Java code, if the checked exception is not processed by the catch
or throws
keyword, it cannot pass the compilation.
For example, the following code for IO operation:
Except for RuntimeException
and its subclasses, the other Exception
class and its subclasses are all checked exceptions. Common checked exceptions are: IO related exceptions, ClassNotFoundException
, SQLException
.
Unchecked Exception means unchecked exception . During the compilation process of Java code, we can compile normally even if we do not handle unchecked exception.
RuntimeException
and its subclasses are collectively referred to as unchecked exceptions.
-
NullPointerException
(null pointer error) -
IllegalArgumentException
(parameter error such as method input parameter type error) -
NumberFormatException
(string to number malformed, subclass ofIllegalArgumentException
) -
ArrayIndexOutOfBoundsException
(Array out of bounds error) -
ClassCastException
(type conversion error) -
ArithmeticException
(arithmetic error) -
SecurityException
(security error such as insufficient permissions) -
UnsupportedOperationException
(unsupported operation error such as duplicate creation of the same user) - ......
What are the common methods of the Throwable class?
-
String getMessage()
: return a brief description of when the exception occurred -
String toString()
: Returns the detailed information when the exception occurred -
String getLocalizedMessage()
: Returns the localized information of the exception object. Override this method with a subclass ofThrowable
to generate localized information. If the subclass does not override this method, the information returned by this method is the same as that returned bygetMessage()
-
void printStackTrace()
: Print on the consoleThrowable
Exception information encapsulated by the object
How is try-catch-finally used?
-
try
Block: Used to catch exceptions. It can be followed by zero or morecatch
blocks, if there is nocatch
block, it must be followed by afinally
block. - *
catch
Block: Used to handle exceptions caught by try. -
finally
block: The statements in thefinally
block are executed regardless of whether the exception is caught or handled. When the ---c38116bcc6778b999f64b41b7c9517bc statement is executed before the methodreturn
statement when the ---c38116bcc6778b999f64b41b7c9517bc statement is encountered in thetry
block or thecatch
block, the ---1ea4e36e0ce5daa465---341 block will be executed before the methodfinally
statement.
Code example:
try {
System.out.println("Try to do something");
throw new RuntimeException("RuntimeException");
} catch (Exception e) {
System.out.println("Catch Exception -> " + e.getMessage());
} finally {
System.out.println("Finally");
}
output:
Try to do something
Catch Exception -> RuntimeException
Finally
Note: Do not use return in a finally block! When both a try statement and a finally statement have return statements, the return statement in the try block is ignored. This is because the return value in the try statement will be temporarily stored in a local variable. When the return in the finally statement is executed, the value of this local variable becomes the return value in the finally statement.
It is clearly mentioned in the official jvm documentation :
If the
try
clause executes a _return_, the compiled code does the following:
- Saves the return value (if any) in a local variable.
- Executes a jsr to the code for the
finally
clause.- Upon return from the
finally
clause, returns the value saved in the local variable.
Code example:
public static void main(String[] args) {
System.out.println(f(2));
}
public static int f(int value) {
try {
return value * value;
} finally {
if (value == 2) {
return 0;
}
}
}
output:
0
Will the code in finally be executed?
uncertain! In some cases, the code in finally will not be executed.
For example, if the virtual machine is terminated before finally, the code in finally will not be executed.
try {
System.out.println("Try to do something");
throw new RuntimeException("RuntimeException");
} catch (Exception e) {
System.out.println("Catch Exception -> " + e.getMessage());
// 终止当前正在运行的Java虚拟机
System.exit(1);
} finally {
System.out.println("Finally");
}
output:
Try to do something
Catch Exception -> RuntimeException
In addition, in the following two special cases, the code of the finally
block will not be executed:
- The thread in which the program resides dies.
- Turn off the CPU.
Related issue: https://github.com/Snailclimb/JavaGuide/issues/190 .
🧗🏻 Advanced: From the perspective of bytecode analysis try catch finally
the implementation principle behind this syntactic sugar.
How to use try-with-resources
instead of try-catch-finally
?
- Scope (definition of resource): Any object that implements
java.lang.AutoCloseable
orjava.io.Closeable
- Execution order of closing resources and finally blocks: In a
try-with-resources
statement, any catch or finally blocks run after the declared resource is closed
"Effective Java" clearly states:
In the face of resources that must be closed, we should always usetry-with-resources
instead oftry-finally
. The resulting code is shorter and cleaner, and the resulting exceptions are more useful to us.try-with-resources
statement makes it easier to write code for resources that must be closed, which is almost impossible withtry-finally
.
Java 中InputStream
、 OutputStream
、 Scanner
、 PrintWriter
close()
方法To manually close, under normal circumstances, we use the try-catch-finally
statement to achieve this requirement, as follows:
//读取文本文件的内容
Scanner scanner = null;
try {
scanner = new Scanner(new File("D://read.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
Use the try-with-resources
statement after Java 7 to transform the above code:
try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
Of course, when multiple resources need to be closed, using try-with-resources
is also very simple to implement. If you still use try-catch-finally
it may bring many problems.
Multiple resources can be declared in a try-with-resources
block by separating them with semicolons.
try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
int b;
while ((b = bin.read()) != -1) {
bout.write(b);
}
}
catch (IOException e) {
e.printStackTrace();
}
What should be paid attention to in abnormal use?
- Do not define exceptions as static variables, because this will cause confusion in the exception stack. Every time an exception is thrown manually, we need to manually throw a new exception object.
- The exception information thrown must be meaningful.
- It is recommended to throw a more specific exception such as when the string is converted to a number in the wrong format, it should be thrown
NumberFormatException
instead of its parent classIllegalArgumentException
. - After using the log to print the exception, don't throw the exception again (the two should not exist in a piece of code logic at the same time).
- ......
Generics
What are generics? what's the effect?
Java Generics (Generics) is a new feature introduced in JDK 5. Using generic parameters can enhance the readability and stability of the code.
The compiler can detect generic parameters and specify the incoming object type through generic parameters. For example ArrayList<Persion> persons = new ArrayList<Persion>()
this line of code indicates that the ArrayList
object can only be passed in Persion
object, and an error will be reported if other types of objects are passed in.
ArrayList<E> extends AbstractList<E>
And, the native List
return type is Object
, you need to manually convert the type to use, and the compiler will automatically convert it after using generics.
What are the ways to use generics?
There are generally three ways to use generics: generic classes , generic interfaces , and generic methods .
1. Generic class :
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey(){
return key;
}
}
How to instantiate a generic class:
Generic<Integer> genericInteger = new Generic<Integer>(123456);
2. Generic interface :
public interface Generator<T> {
public T method();
}
Implement a generic interface without specifying a type:
class GeneratorImpl<T> implements Generator<T>{
@Override
public T method() {
return null;
}
}
Implement a generic interface, specifying the type:
class GeneratorImpl<T> implements Generator<String>{
@Override
public String method() {
return "hello";
}
}
3. Generic method :
public static < E > void printArray( E[] inputArray )
{
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
use:
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3 };
String[] stringArray = { "Hello", "World" };
printArray( intArray );
printArray( stringArray );
Note:public static < E > void printArray( E[] inputArray )
is generally called a static generic method; in java a generic is just a placeholder and must be used after passing a type. A class can only pass type parameters when it is instantiated. Since the loading of static methods precedes the instantiation of classes, that is to say, the generics in the class have not passed the real type parameters, and the loading of static methods has been completed. So there is no way for static generic methods to use generics declared on the class. You can only use your own declaration<E>
Where are generics used in the project?
- Custom interface general return result
CommonResult<T>
Through parametersT
The data type of the result can be dynamically specified according to the specific return type - Definition
Excel
processing classExcelUtil<T>
for dynamic specificationExcel
exported data type - Build a collection tool class (refer to the
Collections
sort
,binarySearch
methods in ---59ae994d2f35cbf1962ced45a3f48b64---). - ......
reflection
What is reflection?
If you have studied the underlying principles of the framework or we have written the framework ourselves, you must be familiar with the concept of reflection.
Reflection is called the soul of the framework mainly because it gives us the ability to analyze classes at runtime and execute methods in them. Through reflection you can get all the properties and methods of any class, and you can also call these methods and properties.
Advantages and disadvantages of reflection mechanism
- Advantages : It can make our code more flexible and provide convenience for various frameworks to provide out-of-the-box functions
- Disadvantage : It gives us the ability to analyze operation classes at runtime, which also increases security issues. For example, the security check of generic parameters can be ignored (the security check of generic parameters occurs at compile time). In addition, the performance of reflection is also slightly worse, but it has little effect on the framework. Java Reflection: Why is it so slow?
Reflection application scenarios
As we usually write business code most of the time, we rarely come into contact with the scene of directly using the reflection mechanism.
However, that doesn't mean reflection is useless. On the contrary, it is because of reflection that you can use various frameworks so easily. Frameworks like Spring/Spring Boot, MyBatis, etc. use a lot of reflection mechanisms.
Dynamic proxies are also heavily used in these frameworks, and the implementation of dynamic proxies also relies on reflection.
For example, the following is the sample code for implementing dynamic proxy through JDK, which uses the reflection class Method
to call the specified method.
public class DebugInvocationHandler implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private final Object target;
public DebugInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("before method " + method.getName());
Object result = method.invoke(target, args);
System.out.println("after method " + method.getName());
return result;
}
}
In addition, implementations like annotations , a great tool in Java, use reflection.
Why when you use Spring, a @Component
annotation declares a class as Spring Bean? Why do you read the value in the configuration file through a @Value
annotation? How exactly does it work?
These are all because you can analyze classes based on reflection, and then get annotations on class/property/method/method parameters. After you get the annotation, you can do further processing.
annotation
Annotation
(annotation) is a new feature introduced in Java5, which can be regarded as a special annotation, mainly used to modify classes, methods or variables.
The essence of the annotation is a special interface that inherits Annotation
:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
public interface Override extends Annotation{
}
The annotation will only take effect after it is parsed. There are two common parsing methods:
- Direct scanning during compilation: The compiler scans the corresponding annotations and processes them when compiling Java code. For example, if a method uses the
@Override
annotation, the compiler will detect whether the current method has been rewritten when compiling. The corresponding method of the parent class. - The runtime is processed by reflection : the annotations that come with the framework (such as
@Value
and@Component
of the Spring framework) are processed by reflection.
JDK provides many built-in annotations (such as @Override
, @Deprecated
), and we can also customize annotations.
I/O
What is serialization? What is deserialization?
If we need to persist Java objects, such as saving Java objects in files, or transmitting Java objects over the network, serialization is required in these scenarios.
simply put:
- Serialization : The process of converting a data structure or object into a stream of binary bytes
- Deserialization : The process of converting the binary byte stream generated during serialization into a data structure or object
For an object-oriented programming language such as Java, what we serialize is an object (Object), that is, an instantiated class (Class), but in a semi-object-oriented language such as C++, the struct (structure) definition is the data structure type, and class corresponds to the object type.
Wikipedia describes serialization as follows:
Serialization, in data processing in computer science, refers to the conversion of data structures or object states into a usable format (eg, as a file, buffered, or sent over a network) for subsequent use in the same or another format. In a computer environment, the process of restoring the original state. When retrieving the result of bytes in serialized format, it can be used to produce a copy with the same semantics as the original object. For many objects, such as complex objects that use a lot of references, this serialization reconstruction process is not easy. Object serialization in object orientation does not generalize the functions to which the original object was related. This process is also known as object marshalling. The reverse operation of extracting a data structure from a sequence of bytes is deserialization (also known as unmarshalling, deserialization, unmarshalling).
To sum up: The main purpose of serialization is to transfer objects over the network or to store objects in the file system, database, and memory.
<p style="text-align:right;font-size:13px;color:gray"> https://www.corejavaguru.com/java/serialization/interview-questions-1 </p>
What if some fields in Java serialization do not want to be serialized?
For variables that do not want to be serialized, use the transient
keyword modification.
transient
The function of the keyword is to prevent the serialization of variables modified with this keyword in the instance; when the object is deserialized, the variable value modified by transient
will not be are persisted and restored.
About transient
There are a few more notes:
-
transient
Can only modify variables, not classes and methods. -
transient
modified variable, the variable value will be set to the default value of the type after deserialization. For example, if it is a modification of typeint
, the result after deserialization is0
. -
static
Since the variable does not belong to any object (Object), it will not be serialized with or without thetransient
keyword modification.
Two common ways to get keyboard input
Method 1: Via Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();
Method 2: Via BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
What are the types of IO streams in Java?
- According to the flow direction of the flow, it can be divided into input flow and output flow;
- According to the operation unit, it can be divided into byte stream and character stream;
- According to the role of the flow, it is divided into node flow and processing flow.
The Java IO stream involves more than 40 classes. These classes look messy, but they are actually very regular, and there is a very close relationship between them. The more than 40 classes of the Java IO stream are derived from the following 4 abstract classes derived from the base class.
- InputStream/Reader: The base class for all input streams, the former is a byte input stream and the latter is a character input stream.
- OutputStream/Writer: The base class for all output streams, the former is a byte output stream and the latter is a character output stream.
The structure diagram is classified according to the operation mode:
Classification structure diagram by operation object:
Since there is a byte stream, why should there be a character stream?
The essence of the question wants to ask: whether it is file reading or writing or network transmission and reception, the smallest storage unit of information is bytes, so why are I/O stream operations divided into byte stream operations and character stream operations?
Answer: The character stream is obtained by converting bytes by the Java virtual machine. The problem is that this process is still very time-consuming, and if we don't know the encoding type, it is easy to have garbled characters. Therefore, the I/O stream simply provides an interface to directly manipulate characters, which is convenient for us to perform stream operations on characters. If audio files, pictures and other media files are better to use byte streams, if characters are involved, it is better to use character streams.
postscript
Focus on Java original dry goods sharing, the junior open source JavaGuide ("Java Learning + Interview Guide" covers the core knowledge that most Java programmers need to master. Prepare for Java interviews, JavaGuide is the first choice!), currently has 120k+ Stars.
Originality is not easy, welcome to like and share, welcome to follow my account in Sifu , I will continue to share original dry goods! Come on, go!
If this article is helpful to you, please like and share, it is very important for me to continue to share & create high-quality articles. Thanks 🙏🏻
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。