Java Basics
-boolean values true and false -all byte values -short values between -128 and 127 -int values between -128 and 127 -char in the range \u0000 to \u007F
When using the packaging types corresponding to these basic types, you can directly use the objects in the buffer pool.
- [一, data type] (#一 data type)
- [Package Type](#Package Type)
- [Cache Pool](#Cache Pool)
- 二、String
- Overview
- [Immutable benefits] (#immutable benefits)
- String, StringBuffer and StringBuilder
- String Pool
- new String(“abc”)
- 三、算
- [Parameter transfer](#Parameter transfer)
- float and double
- [Implicit Type Conversion] (#Implicit Type Conversion)
- switch
- [四. Inheritance] (#四 Inheritance)
- [Access Authority](#Access Authority)
- [Abstract Class and Interface](#Abstract Class and Interface)
- super
- [Rewrite and reload](#Rewrite and reload)
- [五.Object general method] (#五object-common method)
- Overview
- equals()
- hashCode()
- toString()
- clone()
- [六、Keywords] (#六Keywords)
- final
- static
- [七, reflection] (#七 Reflection)
- [八、Exception] (#八Exception)
- 九、generic
- [十、Notes] (#十Notes)
- [11. Features] (#11 Features)
- [New features of each version of Java](#java-New features of each version)
- [The difference between Java and C++](#java-and -c-difference)
- JRE or JDK
- [Reference material](#Reference material)
One, data type
type of packaging
Eight basic types:
-boolean/1 -byte/8 -char/16 -short/16 -int/32 -float/32 -long/64 -double/64
The basic types have corresponding packaging types, and the assignment between the basic types and their corresponding packaging types is completed by automatic boxing and unboxing.
1 | Integer x = 2; // boxing |
Cache Pool
The difference between new Integer(123) and Integer.valueOf(123) is:
-new Integer(123) will create a new object every time; -Integer.valueOf(123) will use the object in the buffer pool, and multiple calls will get a reference to the same object.
1 | Integer x = new Integer(123); |
The implementation of the valueOf() method is relatively simple, that is, first determine whether the value is in the buffer pool, and if so, return the contents of the buffer pool directly.
1 | public static Integer valueOf(int i) { |
In Java 8, the default size of the Integer buffer pool is -128~127.
1 | static final int low = -128; |
The compiler will call the valueOf() method during the auto-boxing process, so multiple Integer instances are created using auto-boxing and have the same value, then the same object will be referenced.
1 | Integer m = 123; |
The buffer pools corresponding to the basic types are as follows:
-boolean values true and false -all byte values -short values between -128 and 127 -int values between -128 and 127 -char in the range \u0000 to \u007F
When using the packaging types corresponding to these basic types, you can directly use the objects in the buffer pool.
StackOverflow: Differences between new Integer(123), Integer.valueOf(123) and just 123
Two, String
Overview
String is declared as final, so it cannot be inherited.
The char array is used internally to store data. The array is declared as final, which means that after the value array is initialized, no other arrays can be referenced. And there is no method to change the value array inside String, so String can be guaranteed to be immutable.
1 | public final class String |
Immutable benefits
1. The hash value can be cached
Because the hash value of String is often used, for example, String is used as the key of HashMap. The immutable feature can make the hash value immutable, so only one calculation is required.
2. Need for String Pool
If a String object has already been created, then a reference will be taken from the String Pool. Only String is immutable, it is possible to use String Pool.
3. Security
String is often used as a parameter, and String immutability can ensure that the parameter is immutable. For example, if String is variable as a network connection parameter, the String is changed during the network connection. The party that changes the String object thinks that it is connected to another host, but the actual situation is not necessarily the case.
4. Thread safety
String immutability is inherently thread-safe and can be used safely in multiple threads.
Program Creek: Why String is immutable in Java?
String, StringBuffer and StringBuilder
1. Variability
-String is immutable -StringBuffer and StringBuilder are variable
2. Thread safety
-String is immutable, so it is thread-safe -StringBuilder is not thread safe -StringBuffer is thread-safe and uses synchronized internally for synchronization
StackOverflow: String, StringBuffer, and StringBuilder
String Pool
The String Pool stores all literal strings, which are determined at compile time. Not only that, you can also use String’s intern() method to add strings to the String Pool during operation.
When a string calls the intern() method, if a string already exists in the String Pool and the string value is equal (using the equals() method to determine), then a reference to the string in the String Pool will be returned; otherwise, A new string will be added to the String Pool and a reference to this new string will be returned.
In the following example, s1 and s2 use the new String() method to create two different strings, while s3 and s4 obtain a string reference through the s1.intern() method. intern() first puts the string referenced by s1 into the String Pool, and then returns the string reference. Therefore, s3 and s4 refer to the same string.
1 | String s1 = new String("aaa"); |
If the string is created in the form of “bbb” literal, the string will be automatically put into the String Pool.
1 | String s5 = "bbb"; |
Before Java 7, String Pool was placed in the runtime constant pool, which belonged to the permanent generation. In Java 7, String Pool was moved to the heap. This is because the space of the permanent generation is limited, which will cause OutOfMemoryError in scenarios where a large number of strings are used.
-StackOverflow: What is String interning? -In-depth analysis of String#intern
new String(“abc”)
In this way, a total of two string objects will be created (provided that there is no “abc” string object in the String Pool).
-“abc” is a string literal, so a string object will be created in the String Pool at compile time, pointing to this “abc” string literal; -Using new will create a string object in the heap.
Create a test class and use this method in its main method to create a string object.
1 | public class NewStringTest { |
Use javap -verbose to decompile and get the following:
1 | // ... |
In the Constant Pool, #19 stores the string literal “abc”, #3 is the string object of the String Pool, and it points to the string literal #19. In the main method, line 0: uses new #2 to create a string object in the heap, and uses ldc #3 to use the string object in the String Pool as a parameter of the String constructor.
The following is the source code of the String constructor. You can see that when a string object is used as the constructor parameter of another string object, the contents of the value array will not be copied completely, but will all point to the same value array.
1 | public String(String original) { |
Three, operation
Parameter passing
Java parameters are passed to the method in the form of value transfer, not by reference.
In the following code, the dog of Dog dog is a pointer, which stores the address of the object. When passing a parameter to a method, it essentially passes the address of the object to the formal parameter by value. Therefore, in the method, the pointers refer to other objects, then the two pointers point to completely different objects at this time, and when one party changes the content of the object pointed to, it has no effect on the other party.
1 | public class Dog { |
1 | public class PassByValueExample { |
If you change the field value of the object in the method, the field value of the original object will be changed, because the content pointed to by the same address is changed.
1 | class PassByValueExample { |
[StackOverflow: Is Java “pass-by-reference” or “pass-by-value”?](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by -value)
float and double
Java cannot implicitly perform downcasting because it will reduce the accuracy.
1.1 The literal is a double type, and 1.1 cannot be directly assigned to a float variable, because this is a downcast.
1 | // float f = 1.1; |
The 1.1f literal is the float type.
1 | float f = 1.1f; |
Implicit type conversion
Because the literal 1 is of the int type, it has higher precision than the short type, so the int type cannot be implicitly converted to the short type.
1 | short s1 = 1; |
But using += or ++ operator can perform implicit type conversion.
1 | s1 += 1; |
The above statement is equivalent to downcasting the calculation result of s1 + 1:
1 | s1 = (short) (s1 + 1); |
[StackOverflow: Why don’t Java’s +=, -=, *=, /= compound assignment operators require casting?](https://stackoverflow.com/questions/8710619/why-dont-javas-compound-assignment-operators -require-casting)
switch
Starting from Java 7, String objects can be used in switch conditional judgment statements.
1 | String s = "a"; |
Switch does not support long, because the original design intention of switch is to make equivalent judgments for only a few values. If the value is too complicated, then if is more appropriate.
1 | // long x = 111; |
StackOverflow: Why can’t your switch statement data type be long, Java?
Four, inheritance
access permission
There are three access modifiers in Java: private, protected, and public. If no access modifier is added, it means package-level visibility.
You can add access modifiers to the class or members (fields and methods) in the class.
-Class visible means that other classes can use this class to create instance objects. -Member visible means that other classes can use instance objects of this class to access the member;
Protected is used to modify members, which means that members are visible to subclasses in the inheritance system, but this access modifier has no meaning for classes.
A well-designed module hides all implementation details and clearly separates its API from its implementation. Modules only communicate through their APIs. A module does not need to know the internal workings of other modules. This concept is called information hiding or encapsulation. Therefore, access rights should be as far as possible to prevent each class or member from being accessed by the outside world.
If the method of the subclass overrides the method of the parent class, the access level of the method in the subclass is not allowed to be lower than the access level of the parent class. This is to ensure that the subclass instance can be used wherever the parent class instance can be used, that is, to ensure that the Richter substitution principle is met.
The field must not be public, because doing so will lose control of the modification behavior of this field, and the client can modify it at will. For example, in the following example, AccessExample has a public id field. If at a certain moment, we want to use int to store the id field, then we need to modify all the client code.
1 | public class AccessExample { |
You can use public getter and setter methods to replace public fields, so that you can control the behavior of modifying the fields.
1 | public class AccessExample { |
But there are exceptions. If it is a package-level private class or a private nested class, then directly exposing the members will not have a particularly big impact.
1 | public class AccessWithInnerClassExample { |
Abstract class and interface
1. Abstract class
Both abstract classes and abstract methods are declared using the abstract keyword. Abstract classes generally contain abstract methods, and abstract methods must be located in abstract classes.
The biggest difference between abstract classes and ordinary classes is that abstract classes cannot be instantiated, and only subclasses can be instantiated by inheriting the abstract class.
1 | public abstract class AbstractClassExample { |
1 | public class AbstractExtendClassExample extends AbstractClassExample { |
1 | // AbstractClassExample ac1 = new AbstractClassExample(); //'AbstractClassExample' is abstract; cannot be instantiated |
2. Interface
An interface is an extension of an abstract class. Before Java 8, it can be regarded as a completely abstract class, which means that it cannot have any method implementation.
Starting from Java 8, interfaces can also have default method implementations. This is because the maintenance cost of interfaces that do not support default methods is too high. Before Java 8, if an interface wanted to add a new method, then all classes that implemented the interface had to be modified.
The members (fields + methods) of the interface are all public by default, and are not allowed to be defined as private or protected.
The fields of the interface are static and final by default.
1 | public interface InterfaceExample { |
1 | public class InterfaceImplementExample implements InterfaceExample { |
1 | // InterfaceExample ie1 = new InterfaceExample(); //'InterfaceExample' is abstract; cannot be instantiated |
3. Comparison
-From a design perspective, an abstract class provides an IS-A relationship, so it must satisfy the Li substitution principle, that is, subclass objects must be able to replace all parent objects. The interface is more like a LIKE-A relationship, it only provides a way to implement the contract, and does not require an IS-A relationship between the interface and the class that implements the interface. -From the point of view of use, a class can implement multiple interfaces, but cannot inherit multiple abstract classes. -The fields of the interface can only be of static and final types, while the fields of the abstract class have no such restriction. -The members of the interface can only be public, and the members of the abstract class can have multiple access rights.
4. Use selection
Use interface:
-Need to make irrelevant classes implement a method, for example, irrelevant classes can implement the compareTo() method in the Compareable interface; -Need to use multiple inheritance.
Use abstract classes:
-Need to share code among several related classes. -Need to be able to control the access rights of inherited members, not all of them are public. -Need to inherit non-static and non-constant fields.
In many cases, interfaces take precedence over abstract classes. Because the interface does not have strict class hierarchy requirements for abstract classes, you can flexibly add behavior to a class. And starting from Java 8, the interface can also have a default method implementation, making the cost of modifying the interface also very low.
-In-depth understanding of abstract class and interface -When to Use Abstract Class and Interface
super
-Access to the constructor of the parent class: You can use the super() function to access the constructor of the parent class, thereby entrusting the parent class to complete some initialization work. -Access the members of the parent class: If the child class overrides a method of the parent class, it can be achieved by using the super keyword to refer to the method of the parent class.
1 | public class SuperExample { |
1 | public class SuperExtendExample extends SuperExample { |
1 | SuperExample e = new SuperExtendExample(1, 2, 3); |
1 | SuperExample.func() |
Rewrite and reload
1. Override
Existing in the inheritance system, it means that the child class implements a method that is exactly the same as the method declaration of the parent class.
In order to satisfy the principle of Li substitution, rewriting has the following two restrictions:
-The access authority of the subclass method must be greater than or equal to the parent class method; -The return type of the subclass method must be the return type of the parent method or its subtype.
Using the @Override annotation, you can let the compiler help to check whether the above two restrictions are met.
2. Overload
Existing in the same class means that a method has the same name as an existing method, but at least one parameter type, number, and order are different.
It should be noted that if the return value is different, everything else is the same, which is not considered an overload.
Five, Object general method
Overview
1 |
|
equals()
1. Equivalence relationship
Ⅰ Reflexivity
1 | x.equals(x); // true |
Ⅱ Symmetry
1 | x.equals(y) == y.equals(x); // true |
Ⅲ Transitivity
1 | if (x.equals(y) && y.equals(z)) |
Ⅳ Consistency
The result of calling equals() multiple times remains unchanged
1 | x.equals(y) == x.equals(y); // true |
Ⅴ Comparison with null
Calling x.equals(null) on any object x that is not null will result in false
1 | x.equals(null); // false; |
2. Equivalence and equality
-For basic types, == determines whether two values are equal. Basic types have no equals() method. -For reference types, == judges whether two variables refer to the same object, and equals() judges whether the referenced objects are equivalent.
1 | Integer x = new Integer(1); |
3. Implementation
-Check whether it is a reference to the same object, if it is a direct return true; -Check whether it is the same type, if not, return false directly; -Transform the Object object; -Determine whether each key field is equal.
1 | public class EqualExample { |
hashCode()
hashCode() returns the hash value, and equals() is used to determine whether two objects are equivalent. Two objects with equivalent hash values must be the same, but two objects with the same hash value are not necessarily equivalent.
When overriding the equals() method, you should always overwrite the hashCode() method to ensure that the hash values of the two equivalent objects are also equal.
In the following code, two equivalent objects are created and added to the HashSet. We want to treat these two objects as the same and only add one object to the collection, but because EqualExample does not implement the hasCode() method, the hash values of these two objects are different, which eventually leads to the addition of two objects to the collection. Price object.
1 | EqualExample e1 = new EqualExample(1, 1, 1); |
The ideal hash function should have uniformity, that is, unequal objects should be evenly distributed to all possible hash values. This requires the hash function to take all domain values into consideration. Each field can be regarded as a certain digit of R system, and then form an integer of R system. R generally takes 31, because it is an odd prime number. If it is an even number, when the multiplication overflows, the information will be lost, because multiplying by 2 is equivalent to shifting one bit to the left.
Multiplying a number with 31 can be converted into shift and subtraction: 31*x == (x<<5)-x
, the compiler will automatically perform this optimization.
1 |
|
toString()
By default, the form ToStringExample@4554617c is returned , where the value after @ is the unsigned hexadecimal representation of the hash code.
1 | public class ToStringExample { |
1 | ToStringExample example = new ToStringExample(123); |
1 | ToStringExample@4554617c |
clone()
1. cloneable
Clone() is the protected method of Object. It is not public. If a class does not explicitly override clone(), other classes cannot directly call the clone() method of an instance of that class.
1 | public class CloneExample { |
1 | CloneExample e1 = new CloneExample(); |
Rewrite clone() to get the following implementation:
1 | public class CloneExample { |
1 | CloneExample e1 = new CloneExample(); |
1 | java.lang.CloneNotSupportedException: CloneExample |
The CloneNotSupportedException is thrown above because CloneExample does not implement the Cloneable interface.
It should be noted that the clone() method is not a method of the Cloneable interface, but a protected method of Object. The Cloneable interface only stipulates that if a class does not implement the Cloneable interface and calls the clone() method, a CloneNotSupportedException will be thrown.
1 | public class CloneExample implements Cloneable { |
2. Shallow copy
The reference types of the copied object and the original object refer to the same object.
1 | public class ShallowCloneExample implements Cloneable { |
1 | ShallowCloneExample e1 = new ShallowCloneExample(); |
3. Deep copy
The reference types of the copied object and the original object refer to different objects.
1 | public class DeepCloneExample implements Cloneable { |
1 | DeepCloneExample e1 = new DeepCloneExample(); |
4. Alternatives to clone()
Using the clone() method to copy an object is complicated and risky, it throws an exception, and also requires type conversion. As mentioned in the Effective Java book, it is best not to use clone(), you can use the copy constructor or copy factory to copy an object.
1 | public class CloneConstructorExample { |
1 | CloneConstructorExample e1 = new CloneConstructorExample(); |
Six, keywords
final
1. Data
The declared data is a constant, which can be a compile-time constant or a constant that cannot be changed after being initialized at runtime.
-For basic types, final keeps the value unchanged; -For reference types, final makes the reference unchanged, so other objects cannot be referenced, but the referenced object itself can be modified.
1 | final int x = 1; |
2. Method
The declaration method cannot be overridden by subclasses.
The private method is implicitly designated as final. If the method defined in the subclass has the same signature as a private method in the base class, then the method of the subclass is not overriding the base class method, but is defined in the subclass A new approach.
3. Class
The declared class is not allowed to be inherited.
static
1. Static variables
-Static variable: also known as class variable, which means that this variable belongs to the class. All instances of the class share the static variable, which can be accessed directly through the class name. There is only one copy of static variables in memory. -Instance variable: Every time an instance is created, an instance variable will be generated, and it will live and die with the instance.
1 | public class A { |
2. Static method
The static method exists when the class is loaded, and it does not depend on any instance. Therefore, a static method must have an implementation, which means that it cannot be an abstract method.
1 | public abstract class A { |
Only the static fields and static methods of the belonging class can be accessed, and the this and super keywords cannot be included in the method.
1 | public class A { |
3. Static statement block
The static statement block runs once when the class is initialized.
1 | public class A { |
1 | 123 |
4. Static inner class
Non-static inner classes depend on instances of outer classes, while static inner classes do not.
1 | public class OuterClass { |
The static inner class cannot access the non-static variables and methods of the outer class.
5. Static guide package
When using static variables and methods, there is no need to specify the ClassName, thus simplifying the code, but the readability is greatly reduced.
1 | import static com.xxx.ClassName.* |
6. Initialization sequence
Static variables and static statement blocks take precedence over instance variables and ordinary statement blocks. The initialization order of static variables and static statement blocks depends on their order in the code.
1 | public static String staticField = "Static Variable"; |
1 | static { |
1 | public String field = "Instance Variable"; |
1 | { |
The last is the initialization of the constructor.
1 | public InitialOrderTest() { |
In the case of inheritance, the initialization sequence is:
-Parent class (static variable, static statement block) -Subclass (static variable, static statement block) -Parent class (instance variables, ordinary statement blocks) -Parent class (constructor) -Subclass (instance variable, ordinary statement block) -Subclass (constructor)
Seven, reflection
Each class has a Class object, which contains information about the class. When a new class is compiled, a .class file with the same name is generated, and the content of the file holds the Class object.
Class loading is equivalent to the loading of Class objects, and the class is dynamically loaded into the JVM when it is used for the first time. You can also use Class.forName("com.mysql.jdbc.Driver")
to control the loading of the class. This method returns a Class object.
Reflection can provide runtime class information, and this class can be loaded at runtime, even if the class does not exist at compile time.
Class and java.lang.reflect together provide support for reflection. The java.lang.reflect class library mainly contains the following three classes:
-Field: You can use the get() and set() methods to read and modify the fields associated with the Field object; -Method: You can use the invoke() method to call the method associated with the Method object; -Constructor: Constructor can be used to create new objects.
Advantages of Using Reflection:
-Extensibility Features: An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names. -Class Browsers and Visual Development Environments: A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code. -Debuggers and Test Tools: Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discoverable set APIs defined on a class, to insure a high level of code coverage in a test suite.
Drawbacks of Reflection:
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.
-Performance Overhead: Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications. -Security Restrictions: Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet. -Exposure of Internals :Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
-Trail: The Reflection API -In-depth analysis of Java reflection (1)-basics
Eight, abnormal
Throwable can be used to represent any class that can be thrown as an exception. There are two types: Error and Exception. Error is used to indicate errors that the JVM cannot handle. Exception is divided into two types:
-Checked exception: You need to use try…catch… statements to capture and process, and you can recover from the exception; -Unchecked Exception: It is a program runtime error. For example, division by 0 will cause Arithmetic Exception, and the program crashes and cannot be recovered at this time.
-Exception Handling for Getting Started with Java -Java Abnormal Interview Questions and Answers-Part 1
Nine, generic
1 | public class Box |
-Detailed Explanation of Java Generics -10 Java generic interview questions
十、Comment
Java annotations are some meta-information attached to the code, which are used to parse and use some tools during compilation and runtime, and play the function of explanation and configuration. Annotations will not and cannot affect the actual logic of the code, but only play a supporting role.
Annotation Annotation realization principle and custom annotation example
XI. Features
New features in each version of Java
New highlights in Java SE 8
- Lambda Expressions
- Pipelines and Streams
- Date and Time API
- Default Methods
- Type Annotations
- Nashhorn JavaScript Engine
- Concurrent Accumulators
- Parallel operations
- PermGen Error Removed
New highlights in Java SE 7
- Strings in Switch Statement
- Type Inference for Generic Instance Creation
- Multiple Exception Handling
- Support for Dynamic Languages
- Try with Resources
- Java nio Package
- Binary Literals, Underscore in literals
- Diamond Syntax
-Difference between Java 1.8 and Java 1.7? -Java 8 Features
The difference between Java and C++
-Java is a pure object-oriented language. All objects inherit from java.lang.Object. C++ supports both object-oriented and process-oriented for compatibility with C. -Java implements cross-platform features through a virtual machine, but C++ depends on a specific platform. -Java has no pointers, and its references can be understood as safe pointers, while C++ has the same pointers as C. -Java supports automatic garbage collection, while C++ requires manual collection. -Java does not support multiple inheritance and can only achieve the same goal by implementing multiple interfaces, while C++ supports multiple inheritance. -Java does not support operator overloading. Although it is possible to perform addition operations on two String objects, this is an operation supported by the language, not operator overloading, but C++ does. -Java’s goto is a reserved word, but it is not available. C++ can use goto. -Java does not support conditional compilation. C++ uses #ifdef #ifndef and other preprocessing commands to achieve conditional compilation.
What are the main differences between Java and C++?
JRE or JDK
-JRE is the JVM program, Java application need to run on JRE. -JDK is a superset of JRE, JRE + tools for developing java programs. eg, it provides the compiler “javac”
Reference
-Eckel B. Java programming thought [M]. Machinery Industry Press, 2002. -Bloch J. Effective java[M]. Addison-Wesley Professional, 2017.