Java Foundation
encapsulation
Abstract data types are used to encapsulate data and data-based operations to form an indivisible independent entity. The data is protected inside the abstract data type, the internal details are hidden as much as possible, and only some external interfaces are reserved to make it contact with the outside. The user does not need to know the internal details of the object, but can access the object through the interface provided by the object.
advantage:
- Reduce coupling: it can be developed, tested, optimized, used, understood and modified independently
- Reduce the burden of maintenance: it can be more easily understood by programmers, and can not affect other modules during debugging
- Effectively adjust performance: analyze and determine which modules affect the performance of the system
- Improve software reusability
- Reduces the risk of building large systems: even if the entire system is unavailable, these independent modules may be available
The following Person class encapsulates the name, gender, age and other attributes. The outside world can only obtain the name attribute and gender attribute of a Person object through the get() method, but cannot obtain the age attribute, but the age attribute can be used by the work() method.
Note that the gender attribute is stored using the int data type, and the encapsulation makes the user unaware of this implementation detail. When the data type used by the gender attribute needs to be modified, it can also be done without affecting the client code.
public class Person { private String name; private int gender; private int age; public String getName() { return name; } public String getGender() { return gender == 0 ? "man" : "woman"; } public void work() { if (18 <= age && age <= 50) { System.out.println(name + " is working very hard!"); } else { System.out.println(name + " can't work any more!"); } } }
inherit
Inheritance implements the IS-A relationship. For example, Cat and Animal are a kind of IS-A relationship. Therefore, Cat can inherit from Animal to obtain non private attributes and methods of Animal.
Inheritance should follow the Richter substitution principle, and subclass objects must be able to replace all parent objects.
Cat can be used as Animal, that is, cat objects can be referenced with Animal. A parent class reference pointing to a child class object is called an upward transformation.
Animal animal = new Cat();
polymorphic
Polymorphism can be divided into compile time polymorphism and run-time polymorphism:
- Compile time polymorphism mainly refers to method overloading
- Runtime polymorphism means that the specific type pointed to by the object reference defined in the program is determined during runtime
There are three conditions for runtime polymorphism:
- inherit
- Overwrite (overwrite)
- Upward transformation
In the following code, the Instrument class has two subclasses: Wind and focus. They both override the play() method of the parent class, and use the parent class Instrument in the main() method to reference the Wind and focus objects. When the play() method is called by the Instrument reference, the play() method of the class where the actual reference object is located will be executed instead of the method of the Instrument class.
public class Instrument { public void play() { System.out.println("Instument is playing..."); } } public class Wind extends Instrument { public void play() { System.out.println("Wind is playing..."); } } public class Percussion extends Instrument { public void play() { System.out.println("Percussion is playing..."); } } public class Music { public static void main(String[] args) { List<Instrument> instruments = new ArrayList<>(); instruments.add(new Wind()); instruments.add(new Percussion()); for(Instrument instrument : instruments) { instrument.play(); } } }
data type
Packaging type
Eight basic types:
- boolean/1
- byte/8
- char/16
- short/16
- int/32
- float/32
- long/64
- double/64
Each basic type has a corresponding packaging type. The assignment between the basic type and its corresponding packaging type is completed by automatic packing and unpacking.
Integer x = 2; // Packing int y = x; // Unpacking
Cache pool
The difference between new Integer(123) and Integer.valueOf(123) is:
- new Integer(123) creates a new object each time
- Integer.valueOf(123) will use the objects in the cache pool, and multiple calls will get the reference of the same object.
Integer x = new Integer(123); Integer y = new Integer(123); System.out.println(x == y); // false Integer z = Integer.valueOf(123); Integer k = Integer.valueOf(123); System.out.println(z == k); // true
The implementation of valueOf() method is relatively simple, that is, first judge whether the value is in the cache pool, and if so, directly return the contents of the cache pool.
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
In Java 8, the size of Integer cache pool is - 128 ~ 127 by default.
static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; }
The compiler calls the valueOf() method in the buffer pool wide basic type auto boxing procedure, so if multiple Integer instances are created using auto boxing and have the same value, they will reference the same object.
Integer m = 123; Integer n = 123; System.out.println(m == n); // true
The buffer pool corresponding to this type is 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 wrapper types corresponding to these basic types, you can directly use the objects in the buffer pool.
If outside the buffer pool:
Integer m = 323; Integer n = 323; System.out.println(m == n); // false
String
overview
String is declared final, so it cannot be inherited.
The char array is used internally to store data, and the array is declared final, which means that the value array cannot reference other arrays after initialization. Moreover, there is no method to change the value array inside the String, so it can ensure that the String is immutable.
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
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 it only needs to be calculated once.
2. Requirements for string pool
If a string object has been created, the reference will be obtained from the String Pool. String Pool can only be used if string is immutable.
[the external chain picture transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-3duyeQKg-1633419301777)(E:/OneDrive / document / JavaXzM/offer final sprint class / java total knowledge system. assets/f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg)]
3. Safety
String is often used as a parameter. The immutability of string can ensure that the parameter is immutable. For example, if the string is variable as a network connection parameter, the string is changed during the network connection. The party who changes the string object thinks that other hosts are connected, 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.
String, StringBuffer and StringBuilder
1. Variability
- String immutable
- StringBuffer and StringBuilder 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
-
String + String is optimized in the jdk. It will convert string objects into StringBuilder and then append them. However, it cannot be added in the for loop, and many StringBuilder objects will be created.
String.intern()
Using String.intern() can ensure that string variables with the same content reference the same memory object.
In the following example, s1 and s2 create two different objects in the way of new String(), while s3 obtains an object reference through the s1.intern() method. Intern () first puts the object referenced by s1 into the string pool, and then returns the object reference. Therefore, s3 and s1 refer to objects in the same string constant pool.
String s1 = new String("aaa"); String s2 = new String("aaa"); System.out.println(s1 == s2); // false String s3 = s1.intern(); System.out.println(s1.intern() == s3); // true
If you create a string instance in the form of "bbb" using double quotation marks, the newly created object will be automatically placed in the String Pool.
String s4 = "bbb"; String s5 = "bbb"; System.out.println(s4 == s5); // true
Before Java 7, the string constant pool was placed in the runtime constant pool, which is a permanent generation. In Java 7, the string constant pool is moved to the Native Method. This is because the space of the permanent generation is limited. In scenarios where strings are widely used, OutOfMemoryError errors will be caused.
- StackOverflow : What is String interning? (opens new window)
- Deep parsing of String#intern (opens new window)
operation
Parameter transfer
Java parameters are passed into the method in the form of value passing, not by reference.
In the following code, the dog of dog is a pointer that stores the address of the object. When a parameter is passed into a method, it essentially passes the address of the object into the formal parameter as a value. Therefore, if you change the object referenced by the pointer in the method, the two pointers point to completely different objects. Changing the content of the object pointed to by one party has no impact on the other party.
public class Dog { String name; Dog(String name) { this.name = name; } String getName() { return this.name; } void setName(String name) { this.name = name; } String getObjectAddress() { return super.toString(); } }
public class PassByValueExample { public static void main(String[] args) { Dog dog = new Dog("A"); System.out.println(dog.getObjectAddress()); // Dog@4554617c func(dog); System.out.println(dog.getObjectAddress()); // Dog@4554617c System.out.println(dog.getName()); // A } private static void func(Dog dog) { System.out.println(dog.getObjectAddress()); // Dog@4554617c dog = new Dog("B"); System.out.println(dog.getObjectAddress()); // Dog@74a14482 System.out.println(dog.getName()); // B } }
However, changing the field value of the object in the method will change the field value of the original object, because what is changed is the content pointed to by the same address.
class PassByValueExample { public static void main(String[] args) { Dog dog = new Dog("A"); func(dog); System.out.println(dog.getName()); // B } private static void func(Dog dog) { dog.setName("B"); } }
float and double
1.1 literal is of double type and cannot be directly assigned to float variable because it is a downward transformation. Java cannot implicitly perform a downward transformation because it reduces precision.
// float f = 1.1
1.1f literal quantity is the float type.
float f = 1.1f
Implicit type conversion
Because literal 1 is an int type, it is more precise than short type, so it cannot be implicitly converted from int type to short type.
short s1 = 1; // s1 = s1 + 1;
However, you can perform implicit type conversion using the + = operator.
s1 += 1;
The above statement is equivalent to transforming the calculation result of s1 + 1 downward:
s1 = (short) (s1 + 1);
switch
Starting with Java 7, you can use String objects in switch conditional judgment statements.
String s = "a"; switch (s) { case "a": System.out.println("aaa"); break; case "b": System.out.println("bbb"); break; }
Switch does not support long because the original design intention of switch is to judge the equivalence of only a few values. If the values are too complex, it is better to use if.
// long x = 111; // switch (x) { // Incompatible types. Found: 'long', required: 'char, byte, short, int, Character, Byte, Short, Integer, String, or an enum' // case 111: // System.out.println(111); // break; // case 222: // System.out.println(222); // break; // }
StackOverflow : Why can't your switch statement data type be long, Java? (opens new window)
inherit
Access rights
There are three access modifiers in Java: private, protected and public. If you do not add an access modifier, it means that it is visible at the package level.
You can add access modifiers to classes or members (fields and methods) in classes.
- Class visible means that other classes can use this class to create instance objects.
- The member is visible, which means that other classes can access the member with the instance object of this class;
protected is used to modify members, indicating that members are visible to subclasses in the inheritance system, but this access modifier has no meaning to classes.
A well-designed module will hide all the implementation details and clearly isolate its API from its implementation. Modules communicate only through their APIs. One module does not need to know the internal work of other modules. This concept is called information hiding or encapsulation. Therefore, the access authority should try 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 that of the parent class. This is to ensure that subclass instances can be used wherever parent instances can be used, that is, to ensure that the Richter substitution principle is met.
The field must not be public, because if you do so, you will lose control of the field modification behavior, and the client can modify it at will. For example, in the following example, AccessExample has a common id field. If we want to use int to store the id field at a certain time, we need to modify all the client code.
public class AccessExample { public String id; }
Replace the public field with the public getter and setter methods, so that you can control the modification behavior of the field.
public class AccessExample { private int id; public String getId() { return id + ""; } public void setId(String id) { this.id = Integer.valueOf(id); } }
However, there are exceptions. If it is a package level private class or a private nested class, the direct exposure of members will not have a great impact.
public class AccessWithInnerClassExample { private class InnerClass { int x; } private InnerClass innerClass; public AccessWithInnerClassExample() { innerClass = new InnerClass(); } public int getValue() { return innerClass.x; // Direct access } }
Abstract classes and interfaces
abstract class
Concept: an abstract class cannot create an instance. It can only be inherited as a parent class. Abstract class is a parent class abstracted from multiple concrete classes. It has a higher level of abstraction. An abstract class is abstracted from multiple classes with the same characteristics, and this abstract class is used as the template of its subclass, so as to avoid the randomness of subclasses.
characteristic:
- An abstract class cannot be instantiated (because it is not a concrete class, but has a constructor)
- Abstract classes have construction methods that create objects for subclasses
- Abstract methods can be defined in abstract classes (add the abstract keyword in the modification list of methods, and end with ";" and cannot have "{}") public abstract void m1();
- Abstract classes do not necessarily have abstract methods, and abstract methods must be in abstract classes
- A non abstract class inherits an abstract class and must override, implement, and override the abstract methods in the abstract class
- Abstract class member features: 1) member variable: it can be either variable or constant. 2) Construction method: there are construction methods, which are used for initialization of subclass accessing parent class data. 3) Member methods: Methods in abstract classes can be either abstract or non abstract
- In the parent class, non abstract methods: subclass inheritance to improve the reusability of code; Abstract methods: force subclasses to do things
- Problems needing attention in abstract classes: if a class has no abstract methods, it can be an abstract class, that is, there can be no abstract methods in an abstract class. The main purpose of such a class is to prevent the creation of such objects.
- The abstract keyword cannot be used with which keywords.
1) Private conflict: members decorated with private cannot be inherited, so they cannot be overridden by subclasses, while those decorated with abstract are required to be overridden.
2) Final conflict: the final modified member is the final member and cannot be overridden, so static is meaningless;
3) static conflict; static modified members can be accessed directly by class name, but abstract modified members have no method body, so it is meaningless to access members without method body.
Interface
**Concept: * * the preliminary understanding of the interface is a special abstract class. When all the abstract classes are abstract methods, they can be reflected through the interface.
characteristic:
1) Interface cannot be instantiated
2) An interface can only contain declarations of methods
3) The member methods of the interface include methods, properties, indexers, and events
4) An interface cannot contain constants, fields (fields), constructors, destructors, or static members
Differences between abstract classes and interfaces:
- Abstract classes can have constructors, but interfaces cannot have constructors.
- There can be ordinary member variables in abstract classes, but there are no ordinary member variables in interfaces
- Abstract classes can contain static methods, but interfaces cannot contain static methods
- A class can implement multiple interfaces, but can only inherit one abstract class
- Interfaces can be implemented in multiple ways, and abstract classes can only be inherited in a single way
- If the abstract class implements the interface, the methods in the interface can be mapped to the abstract class as abstract methods without implementation, and the methods in the interface can be implemented in subclasses of the abstract class.
Similarities between interface and abstract class:
- Can be inherited
- Can't be instantiated
- Can contain method declarations
- Derived classes must implement unimplemented methods
The biggest benefit of interface is to avoid the complexity and inefficiency caused by multiple inheritance, and can provide the benefits of multiple inheritance at the same time. Both interfaces and abstract classes can present polymorphism, but abstract classes abstract things more for inheritance, expansion and code reuse. The is-a relationship is presented between subclasses and parent classes, and the interface more reflects a behavior constraint and a rule. Once the interface is implemented, the specific implementation of all methods in the interface should be given, That is, the implementation class is meaningful to all methods in the interface.
super
- Accessing the constructor of the parent class: you can use the super() function to access the constructor of the parent class, so as to delegate the parent class to complete some initialization work.
- Accessing members of the parent class: if a child class overrides the implementation of a method in the parent class, you can use the super keyword to reference the implementation of the parent class's method.
public class SuperExample { protected int x; protected int y; public SuperExample(int x, int y) { this.x = x; this.y = y; } public void func() { System.out.println("SuperExample.func()"); } }
public class SuperExtendExample extends SuperExample { private int z; public SuperExtendExample(int x, int y, int z) { super(x, y); this.z = z; } @Override public void func() { super.func(); System.out.println("SuperExtendExample.func()"); } }
Using the Keyword super (opens new window)
Rewriting and overloading
1. Override
Exists in the inheritance system, which means that the subclass implements a method exactly the same as the parent class in method declaration.
In order to meet the Li formula substitution principle, rewriting has the following two limitations:
- The access permission of the subclass method must be greater than or equal to that of the parent method;
- The return type of a subclass method must be the return type of a parent method or its subtype.
Using the @ Override annotation, you can ask the compiler to help check whether the above two constraints 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 is different.
It should be noted that if the return value is different, the others are the same and are not overloaded.
Object general method
overview
public final native Class<?> getClass() public native int hashCode() public boolean equals(Object obj) protected native Object clone() throws CloneNotSupportedException public String toString() public final native void notify() public final native void notifyAll() public final native void wait(long timeout) throws InterruptedException public final void wait(long timeout, int nanos) throws InterruptedException public final void wait() throws InterruptedException protected void finalize() throws Throwable {} @pdai: The code has been copied to the clipboard
equals()
1. Equivalence relation
(1) Reflexivity
x.equals(x); // true
(2) Symmetry
x.equals(y) == y.equals(x); // true
(3) Transitivity
if (x.equals(y) && y.equals(z)) x.equals(z); // true;
(4) Consistency
The equals() method is called multiple times, and the result remains unchanged
x.equals(y) == x.equals(y); // true
(5) Comparison with null
Calling x.equals(null) on any object x that is not null will result in false
x.equals(null); // false;
2. Equals and==
- For primitive types, = = determines whether two values are equal. Primitive types have no equals() method.
- For reference types, = = determines whether two variables refer to the same object, while equals() determines whether the referenced object is equivalent.
Integer x = new Integer(1); Integer y = new Integer(1); System.out.println(x.equals(y)); // true System.out.println(x == y); // false
3. Realization
- Check whether it is a reference to the same object. If yes, return true directly;
- Check whether it is the same type. If not, return false directly;
- Transform the Object object;
- Determine whether each key field is equal.
public class EqualExample { private int x; private int y; private int z; public EqualExample(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EqualExample that = (EqualExample) o; if (x != that.x) return false; if (y != that.y) return false; return z == that.z; } }
hashCode()
hashCode() returns a hash value, and equals() is used to determine whether two objects are equivalent. Two equivalent objects must have the same hash value, but two objects with the same hash value are not necessarily equivalent.
When overriding the equals() method, you should always override 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 the two objects as the same and add only one object to the collection. However, because EqualExample does not implement the hasCode() method, the hash values of the two objects are different, resulting in the addition of two equivalent objects to the collection.
EqualExample e1 = new EqualExample(1, 1, 1); EqualExample e2 = new EqualExample(1, 1, 1); System.out.println(e1.equals(e2)); // true HashSet<EqualExample> set = new HashSet<>(); set.add(e1); set.add(e2); System.out.println(set.size()); // 2
The ideal hash function should be uniform, that is, unequal objects should be evenly distributed over all possible hash values. This requires the hash function to take the values of all fields into account. Each field can be regarded as a bit in r-ary, and then form an r-ary integer. R is generally 31 because it is an odd prime number. If it is an even number, when multiplication overflow occurs, the information will be lost, because multiplying with 2 is equivalent to moving one bit to the left.
A number multiplied by 31 can be converted into shift and subtraction: 31 * x = = (x < < 5) - x, and the compiler will automatically optimize it.
@Override public int hashCode() { int result = 17; result = 31 * result + x; result = 31 * result + y; result = 31 * result + z; return result; }
toString()
Default return ToStringExample@4554617c This form, where the value after @ is the unsigned hexadecimal representation of the hash code.
public class ToStringExample { private int number; public ToStringExample(int number) { this.number = number; } }
ToStringExample example = new ToStringExample(123); System.out.println(example.toString());
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 the class instance.
public class CloneExample { private int a; private int b; }
CloneExample e1 = new CloneExample(); // CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object'
Overriding clone() yields the following implementation:
public class CloneExample { private int a; private int b; @Override protected CloneExample clone() throws CloneNotSupportedException { return (CloneExample)super.clone(); } }
CloneExample e1 = new CloneExample(); try { CloneExample e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); }
java.lang.CloneNotSupportedException: CloneExample
CloneNotSupportedException is thrown above because CloneExample does not implement the clonable interface.
It should be noted that the clone() method is not a method of the clonable interface, but a protected method of Object. The clonable interface only stipulates that if a class does not implement the clonable interface and calls the clone() method, it will throw a clonnotsupportedexception.
public class CloneExample implements Cloneable { private int a; private int b; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
2. Light copy
The reference type of the copy object and the original object refer to the same object.
public class ShallowCloneExample implements Cloneable { private int[] arr; public ShallowCloneExample() { arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i; } } public void set(int index, int value) { arr[index] = value; } public int get(int index) { return arr[index]; } @Override protected ShallowCloneExample clone() throws CloneNotSupportedException { return (ShallowCloneExample) super.clone(); } }
ShallowCloneExample e1 = new ShallowCloneExample(); ShallowCloneExample e2 = null; try { e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } e1.set(2, 222); System.out.println(e2.get(2)); // 222 @pdai: The code has been copied to the clipboard
3. Deep copy
The reference types of the copy object and the original object refer to different objects.
public class DeepCloneExample implements Cloneable { private int[] arr; public DeepCloneExample() { arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i; } } public void set(int index, int value) { arr[index] = value; } public int get(int index) { return arr[index]; } @Override protected DeepCloneExample clone() throws CloneNotSupportedException { DeepCloneExample result = (DeepCloneExample) super.clone(); result.arr = new int[arr.length]; for (int i = 0; i < arr.length; i++) { result.arr[i] = arr[i]; } return result; } } @pdai: The code has been copied to the clipboard
DeepCloneExample e1 = new DeepCloneExample(); DeepCloneExample e2 = null; try { e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } e1.set(2, 222); System.out.println(e2.get(2)); // 2 @pdai: The code has been copied to the clipboard
4. Alternative to clone ()
Using the clone() method to copy an object is complex and risky. It will throw exceptions and require type conversion. As mentioned in the Effective Java book, it is better not to use clone(). You can use a copy constructor or a copy factory to copy an object.
public class CloneConstructorExample { private int[] arr; public CloneConstructorExample() { arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i; } } public CloneConstructorExample(CloneConstructorExample original) { arr = new int[original.arr.length]; for (int i = 0; i < original.arr.length; i++) { arr[i] = original.arr[i]; } } public void set(int index, int value) { arr[index] = value; } public int get(int index) { return arr[index]; } } @pdai: The code has been copied to the clipboard
CloneConstructorExample e1 = new CloneConstructorExample(); CloneConstructorExample e2 = new CloneConstructorExample(e1); e1.set(2, 222); System.out.println(e2.get(2)); // 2
keyword
final
1. Data
The declared data is a constant, which can be a compile time constant or a constant that cannot be changed after initialization at run time.
- 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.
final int x = 1; // x = 2; // cannot assign value to final variable 'x' final A y = new A(); y.a = 1;
2. Method
Declared methods cannot be overridden by subclasses.
The private method is implicitly specified as final. If the signature of the method defined in the subclass is the same as that of a private method in the base class, the subclass method does not override the base class method, but defines a new method in the subclass.
3. Class
Declared classes are not allowed to be inherited.
static
1. Static variables
- Static variable: also known as class variable, that is, this variable belongs to a class. All instances of the class share a static variable, which can be accessed directly through the class name; Static variables exist only once in memory.
- Instance variable: every time an instance is created, an instance variable will be generated, which will live and die with the instance.
public class A { private int x; // Instance variable private static int y; // Static variable public static void main(String[] args) { // int x = A.x; // Non-static field 'x' cannot be referenced from a static context A a = new A(); int x = a.x; int y = A.y; } }
2. Static method
Static methods exist when the class is loaded and do not depend on any instances. Therefore, a static method must be implemented, that is, it cannot be an abstract method.
public abstract class A { public static void func1(){ } // public abstract static void func2(); // Illegal combination of modifiers: 'abstract' and 'static' }
Only static fields and static methods of the class can be accessed, and the method cannot have this and super keywords.
public class A { private static int x; private int y; public static void func1(){ int a = x; // int b = y; // Non-static field 'y' cannot be referenced from a static context // int b = this.y; // 'A.this' cannot be referenced from a static context } }
3. Static statement block
Static statement blocks are run once during class initialization.
public class A { static { System.out.println("123"); } public static void main(String[] args) { A a1 = new A(); A a2 = new A(); } }
123
4. Static internal class
Non static inner classes depend on instances of external classes, while static inner classes do not.
public class OuterClass { class InnerClass { } static class StaticInnerClass { } public static void main(String[] args) { // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context OuterClass outerClass = new OuterClass(); InnerClass innerClass = outerClass.new InnerClass(); StaticInnerClass staticInnerClass = new StaticInnerClass(); } }
Static internal classes cannot access non static variables and methods of external classes.
5. Static guide package
When using static variables and methods, there is no need to specify ClassName, which simplifies the code, but greatly reduces the readability.
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.
public static String staticField = "Static variable";
static { System.out.println("Static statement block"); }
public String field = "Instance variable";
{ System.out.println("Common statement block"); }
The last is the initialization of the constructor.
public InitialOrderTest() { System.out.println("Constructor"); }
In the case of inheritance, the initialization order is:
- Parent class (static variable, static statement block)
- Subclasses (static variables, static statement blocks)
- Parent class (instance variable, common statement block)
- Parent class (constructor)
- Subclasses (instance variables, common statement blocks)
- Subclass (constructor)
reflex
Reflection basis
The function is to identify the type and class information of an object at run time. There are two main ways: one is "traditional" RTTI, which assumes that we already know all types at compile time; The other is the "reflection" mechanism, which allows us to discover and use class information at run time.
Reflection is to map various components of Java classes into Java objects one by one
For example, a class has member variables, methods, construction methods, packages and other information. Using reflection technology, a class can be dissected and each component can be mapped into an object.
Here, we first need to understand the Class and the loading mechanism of the Class; Then, based on this, how do we get the Class and its member variables, methods, constructors, etc. through reflection
Class class
Class class is also a real class, which exists in the java.lang package of JDK. The instance of class class represents the class ans enum or interface and annotation of Java application runtime (each Java class runtime is represented as a class object in the JVM, which can be obtained through methods such as class name. Class, type. getClass(), Class.forName("class name"). Array is also mapped to a class of class object, which is shared by all arrays with the same element type and dimension. The basic types boolean, byte, char, short, int, long, float, double and the keyword void are also represented as class objects.
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement { private static final int ANNOTATION= 0x00002000; private static final int ENUM = 0x00004000; private static final int SYNTHETIC = 0x00001000; private static native void registerNatives(); static { registerNatives(); } /* * Private constructor. Only the Java Virtual Machine creates Class objects. //Private constructor. Only JVM can call to create Class object * This constructor is not used and prevents the default constructor being * generated. */ private Class(ClassLoader loader) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; }
Here we can get the following information:
- Class is also a kind of class, which is different from the class keyword.
- After a manually written class is compiled, a class object will be generated, which represents the type information of the created class, and the class object is saved in a file with the same name. Class (bytecode file)
- For each class identified by the keyword class, there is only one corresponding class object in memory to describe its type information. No matter how many instance objects are created, it is based on a class object.
- Get the binary byte stream defined by a class through its fully qualified name.
- The static storage structure represented by this byte stream is transformed into the runtime data structure of the method area.
- Generate a java.lang.Class object representing this class in the Java heap as an access to these data in the method area.
- Class class only stores private constructors, so the corresponding class object can only be created and loaded by JVM
- The object function of Class is to provide or obtain the type information of an object at runtime, which is very important for reflection technology (Analysis on reflection later).
abnormal
Summary of anomaly basis
- Try, catch and finally cannot be used alone. They can only be try catch, try finally or try catch finally.
- The try statement block monitors the code. If an exception occurs, stop executing the following code, and then hand over the exception to the catch statement block for processing.
- finally, the code in the statement block must be executed, which is often used to recycle resources.
- throws: declare an exception to inform the method caller.
- Throw: throw an exception. Whether the exception is caught or thrown continuously has nothing to do with it.
Java programming ideas, a summary of exceptions.
- Deal with problems at the right level. (an exception is caught when you know how to handle it.)
- Solve the problem and call the method that caused the exception again.
- Make a few fixes, then bypass where the exception occurred and continue.
- Calculate with other data instead of the value expected to be returned by the method.
- Try to finish what can be done in the current running environment, and then throw the same exception to a higher level.
- Try to finish what can be done in the current running environment, and then throw different exceptions to a higher level.
- Terminate the procedure.
- Simplify (if your abnormal pattern makes the problem too complex, it will be very painful to use).
- Make class libraries and programs more secure.
Common exceptions
Some exceptions are provided in Java to describe common errors. Some of these exceptions need to be captured or thrown by programmers, and some are automatically captured and processed by Java virtual machine. Common exception classes in Java:
- RuntimeException
- java.lang.ArrayIndexOutOfBoundsException array index out of bounds exception. Thrown when the index value of the array is negative or greater than or equal to the array size.
- java.lang.ArithmeticException arithmetic condition exception. For example: integer division by zero, etc.
- java.lang.NullPointerException null pointer exception. This exception is thrown when an application attempts to use null where an object is required. For example, call the instance method of null object, access the properties of null object, calculate the length of null object, throw null with throw statement, etc
- java.lang.ClassNotFoundException class exception not found. This exception is thrown when the application attempts to construct a class according to the class name in string form, but cannot find the class file with the corresponding name after traversing the classpath.
- java.lang.NegativeArraySizeException array length is negative exception
- The java.lang.ArrayStoreException array contains an exception thrown by incompatible values
- java.lang.SecurityException security exception
- java.lang.IllegalArgumentException illegal parameter exception
- IOException
- IOException: an exception that may occur when manipulating input and output streams.
- EOFException file ended exception
- FileNotFoundException file found no exception
- other
- ClassCastException type conversion exception class
- The ArrayStoreException array contains an exception thrown by incompatible values
- SQLException operation database exception class
- NoSuchFieldException field found no exception
- The NoSuchMethodException method did not find the exception thrown
- NumberFormatException an exception thrown when a string is converted to a number
- StringIndexOutOfBoundsException exception exception thrown when the string index is out of range
- IllegalAccessException does not allow access to certain types of exceptions
- InstantiationException this exception is thrown when the application attempts to create an instance of a Class using the newInstance() method in the Class class, and the specified Class object cannot be instantiated
Deep understanding of exceptions
How does the JVM handle exceptions?
When it comes to the JVM's exception handling mechanism, you need to mention the Exception Table, which is hereinafter referred to as the Exception Table. Let's take a look at a simple small example of Java exception handling.
public static void simpleTryCatch() { try { testNPE(); } catch (Exception e) { e.printStackTrace(); } }
The above code is a very simple example to capture and handle a potential null pointer exception.
Of course, if we just look at the simple code, it is difficult to see what is profound, and there is no content to be discussed in today's article.
So here we need to use a magic weapon. It is javap, a tool for disassembling class files. Like javac, it is provided by JDK.
Then we use javap to analyze the code (we need to compile it with javac first)
//javap -c Main public static void simpleTryCatch(); Code: 0: invokestatic #3 // Method testNPE:()V 3: goto 11 6: astore_0 7: aload_0 8: invokevirtual #5 // Method java/lang/Exception.printStackTrace:()V 11: return Exception table: from to target type 0 3 6 Class java/lang/Exception
You should smile when you see the above code, because you finally see the Exception table, that is, the Exception table we want to study.
The exception table contains information about one or more exception handlers, including the following
- from the starting point of possible exceptions
- to the end point where exceptions may occur
- target the location of the exception handler after the exception occurred before the above from and to
- type the class information of the exception handled by the exception handler
When is the exception table used
The answer is when an exception occurs, when an exception occurs
- 1. The JVM will look up the exception table in the current exception method and check whether there is an appropriate handler to handle it
- 2. If the current method exception table is not empty, and the exception matches the from and to nodes of the handler, and the type also matches, the JVM calls the caller at the target to handle it.
- 3. If no reasonable handler is found for the previous entry, continue to look for the remaining entries in the exception table
- 4. If the exception table of the current method cannot be processed, look up (pop stack processing) the place where the method has just been called, and repeat the above operation.
- 5. If all stack frames are ejected and still not processed, they will be thrown to the current Thread and the Thread will terminate.
- 6. If the current Thread is the last non daemon Thread and the exception is not handled, the JVM will terminate.
These are some of the mechanisms by which the JVM handles exceptions.
try catch -finally
In addition to the simple try catch, we often use it in combination with finally. Such code
public static void simpleTryCatchFinally() { try { testNPE(); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("Finally"); } }
Again, let's analyze the code using javap
public static void simpleTryCatchFinally(); Code: 0: invokestatic #3 // Method testNPE:()V 3: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 6: ldc #7 // String Finally 8: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 11: goto 41 14: astore_0 15: aload_0 16: invokevirtual #5 // Method java/lang/Exception.printStackTrace:()V 19: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 22: ldc #7 // String Finally 24: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 27: goto 41 30: astore_1 31: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 34: ldc #7 // String Finally 36: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 39: aload_1 40: athrow 41: return Exception table: from to target type 0 3 14 Class java/lang/Exception 0 3 30 any 14 19 30 any
Different from before, there are three pieces of data in the Exception table, and we only caught an Exception. The type of the last two items in the Exception table is any; The above three Exception tables item mean:
- If an Exception of type Exception occurs between 0 and 3, call the Exception handler at position 14.
- If there is any exception between 0 and 3, the handler at position 30 is called
- If there is any exception between 14 and 19 (i.e. catch part), the handler at position 30 is called.
Analyze the above Java code again. finally, the part has been extracted into the try part and the catch part. Let's adjust the code again
public static void simpleTryCatchFinally(); Code: //The try part extracts the finally code. If no exception occurs, execute the output finally operation until goto to position 41, and execute the return operation. 0: invokestatic #3 // Method testNPE:()V 3: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 6: ldc #7 // String Finally 8: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 11: goto 41 //The catch part extracts the finally code. If no exception occurs, execute the output finally operation until get to position 41, and execute the return operation. 14: astore_0 15: aload_0 16: invokevirtual #5 // Method java/lang/Exception.printStackTrace:()V 19: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 22: ldc #7 // String Finally 24: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 27: goto 41 //If the code of the finally part is called, an exception may occur in the try part or the catch part. 30: astore_1 31: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 34: ldc #7 // String Finally 36: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 39: aload_1 40: athrow //If the exception is not caught by catch, but here, after executing the finally statement, still throw the exception and pass it to the caller. 41: return
Catch order problem
The order of our catch in the code determines the position of the exception handler in the exception table. Therefore, the more specific exceptions should be handled first, otherwise the following problems will occur
private static void misuseCatchException() { try { testNPE(); } catch (Throwable t) { t.printStackTrace(); } catch (Exception e) { //error occurs during compilings with tips Exception Java.lang.Exception has already benn caught. e.printStackTrace(); } } @pdai: The code has been copied to the clipboard
This code will cause compilation failure, because catching Throwable first and then Exception will cause the subsequent catch to never be executed.
Return and finally
This is a relatively extreme problem in our extension, that is, if codes like this have both return and finally, will finally lead to execution
public static String tryCatchReturn() { try { testNPE(); return "OK"; } catch (Exception e) { return "ERROR"; } finally { System.out.println("tryCatchReturn"); } } @pdai: The code has been copied to the clipboard
The answer is that finally will execute, so let's use the above method to see why finally will execute.
public static java.lang.String tryCatchReturn(); Code: 0: invokestatic #3 // Method testNPE:()V 3: ldc #6 // String OK 5: astore_0 6: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 9: ldc #8 // String tryCatchReturn 11: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 14: aload_0 15: areturn return OK character string, areturn Means return a reference from a method 16: astore_0 17: ldc #10 // String ERROR 19: astore_1 20: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 23: ldc #8 // String tryCatchReturn 25: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 28: aload_1 29: areturn //Returns the ERROR string 30: astore_2 31: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 34: ldc #8 // String tryCatchReturn 36: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 39: aload_2 40: athrow If catch If there are unhandled exceptions, throw them out. @pdai: The code has been copied to the clipboard
Is the exception time-consuming? Why is it time-consuming? Why does it take time?
Speaking of using abnormally slow, let's first see where the abnormally slow is? How slow is it? The following test cases simply test the time-consuming comparison of creating objects, creating exception objects, and throwing and catching exception objects:
public class ExceptionTest { private int testTimes; public ExceptionTest(int testTimes) { this.testTimes = testTimes; } public void newObject() { long l = System.nanoTime(); for (int i = 0; i < testTimes; i++) { new Object(); } System.out.println("Create object:" + (System.nanoTime() - l)); } public void newException() { long l = System.nanoTime(); for (int i = 0; i < testTimes; i++) { new Exception(); } System.out.println("Create exception object:" + (System.nanoTime() - l)); } public void catchException() { long l = System.nanoTime(); for (int i = 0; i < testTimes; i++) { try { throw new Exception(); } catch (Exception e) { } } System.out.println("Create, throw, and catch exception objects:" + (System.nanoTime() - l)); } public static void main(String[] args) { ExceptionTest test = new ExceptionTest(10000); test.newObject(); test.newException(); test.catchException(); } }
Operation results:
Create object: 575817 Create exception object: 9589080 Create, throw and catch exception object: 47394475
Creating an exception Object takes about 20 times as long as creating an ordinary Object (in fact, the gap will be larger than this figure, because the loop also takes up time. Readers who pursue accuracy can measure the time of empty loop again and subtract this part before comparison). Throwing and catching an exception Object takes about 4 times as long as creating an exception Object.
generic paradigm
The advantage of generics is that type safety is checked at compile time, and all casts are automatic and implicit, which improves the reuse rate of code and avoids problems at run time
annotation
Annotation stores the parameter information in the constant pool of the class file. When creating an instance, it will be obtained through getConstantPool(). It is a byte [] stream and needs to be converted.
Summary:
Annotation @ interface is an interface that implements the annotation interface. When calling getdeclaraedannotations() method, it returns a Proxy $Proxy object, which is created using jdk dynamic Proxy. When using Proxy's newProxyInstance method, it passes in an instance of the interface and InvocationHandler (that is, AnotationInvocationHandler), Finally, a Proxy instance is returned.
During, before creating the proxy object, when parsing the annotation, take the annotation information from the constant pool of the annotation class, including the parameters previously written in the annotation, and then pass these information in as the parameters of the constructor when creating the AnnotationInvocationHandler.
When the method for obtaining the value of the proxy instance is called, the logic in the AnotationInvocationHandler will be called and executed to get out the previously stored annotation information.
reference type
Java provides corresponding encapsulation types for each basic type: Byte, Short, Integer, Long, Float, Double, Character and Boolean. A reference type is an object type whose value is a reference to memory space, that is, an address. (how to manipulate elements in memory)
There are four levels of references in Java: strong reference, soft reference, weak reference and virtual reference. Among the four reference types, only the strong reference java.lang.ref.FinalReference class is visible in the package, and the other three reference types are public and can be used directly in the application. The class structure of reference type is shown in the figure.
reference type
Strong reference (FinalReference)
Strong references are declared by default in Java, such as:
Object obj = new Object(); //As long as obj also points to the Object object, the Object object will not be recycled obj = null; //Manually set null
As long as the strong reference exists, the garbage collector will never recycle the referenced object. Even when the memory is insufficient, the JVM will directly throw OutOfMemoryError and will not recycle the strongly referenced object. If you want to break the connection between the strong reference and the object, you can assign the strong reference to null, so that the JVM can reclaim the object in time.
Features of strong reference:
- Strong references can directly access the target object.
- The object pointed to by a strong reference will not be recycled by the system at any time. The JVM would rather throw an OOM exception than reclaim the object pointed to by a strong reference.
- Strong references can cause memory leaks.
Soft reference
Soft reference is the strongest reference type besides strong reference. You can use soft references through java.lang.ref.SoftReference. When the memory is sufficient, the soft reference object will not be recycled. Only when the memory is insufficient, the system will recycle the soft reference object. If there is still not enough memory after recycling the soft reference object, a memory overflow exception will be thrown. This feature is often used to implement cache technology, such as web page cache, image cache and memory sensitive cache.
The feature of SoftReference is that an instance of SoftReference stores a soft reference to a Java object. The existence of the soft reference does not prevent the garbage collection thread from recycling the Java object. That is, once the SoftReference saves the soft reference to a Java object, the get() method provided by the SoftReference class returns the strong reference of the Java object before the garbage thread recycles the Java object. Once the garbage thread recycles the Java object, the get() method returns null.
The following is an example to illustrate the use of soft reference.
Set the parameter - Xmx2m -Xms2m in the IDE to specify that the heap memory size is 2m.
@Test public void test3(){ MyObject obj = new myObject(); SoftReference sf = new SoftReference<>(obj); obj = null; System.gc(); // byte[] bytes = new byte[1024*100]; // System.gc(); System.out.println("Is it recycled"+sf.get()); }
Operation results:
Is it recycled cn.zyzpp.MyObject@42110406
Now open the commented new byte[1024*100] statement, which requests a large heap space, making the heap memory use tight. And explicitly call GC again. The results are as follows:
Is it recycled null
Indicates that soft references are recycled when the system memory is tight.
Weak reference
The reference strength of weak references is weaker than that of soft references. No matter whether the memory is sufficient or not, as long as the JVM starts garbage collection, those objects associated with weak references will be recycled. Use the java.lang.ref.WeakReference instance to save a weak reference to a Java object.
public void test3(){ MyObject obj = new MyObject(); WeakReference sf = new WeakReference(obj); obj = null; System.out.println("Is it recycled"+sf.get()); System.gc(); System.out.println("Is it recycled"+sf.get()); }
Operation results:
Is it recycled cn.zyzpp.MyObject@42110406 Is it recycled null
Soft reference and weak reference are very suitable for storing dispensable cache data. If you do so, when the system memory is insufficient, these cache data will be recycled and will not lead to memory overflow. When the memory resources are sufficient, these cached data can exist for a long time, so as to accelerate the system.
Phantom reference
Virtual reference is the weakest kind of reference relationship. If an object only holds virtual reference, it may be recycled at any time as it does not have any reference. It is represented by java.lang.ref.PhantomReference class. By looking at the source code of this class, it is found that it has only one constructor and one get() method, and its get() method only returns null, In other words, you will never be able to obtain objects through virtual references. Virtual references must be used together with ReferenceQueue reference queue, which is used to track the garbage collection process.
public class PhantomReference<T> extends Reference<T> { /** * Returns this reference object's referent. Because the referent of a * phantom reference is always inaccessible, this method always returns * <code>null</code>. * * @return <code>null</code> */ public T get() { return null; } public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }
When the garbage collector prepares to recycle an object, if it finds that it still has a virtual reference, it will destroy the object and add the virtual reference to the reference queue after garbage collection. The program can know whether the referenced object will be garbage collected by judging whether a virtual reference has been added to the reference queue. If the program finds that a virtual reference has been added to the reference queue, it can take the necessary action before the memory of the referenced object is reclaimed.
public void test3(){ MyObject obj = new MyObject(); ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>(); PhantomReference sf = new PhantomReference<>(obj,referenceQueue); obj = null; System.out.println("Is it recycled"+sf.get()); System.gc(); System.out.println("Is it recycled"+sf.get()); }
Operation results:
Is it recycled null Is it recycled null
Its purpose is to track the garbage collection process and receive a system notification when the object is collected by the collector. When the garbage collector prepares to recycle an object, if it finds that it still has a virtual reference, it will add the virtual reference to the reference queue after garbage collection, and the object will not be completely destroyed before its associated virtual reference is out of the queue. Therefore, you can check whether there are corresponding virtual references in the reference queue to determine whether the object has been recycled.
If an object has no strong and soft references, it can be cleared by the garbage collector. Before clearing, its finalize method will be called. If an object has been called but has not been released, it will become a virtual reachable object.
ReferenceQueue
The reference queue is represented by the ReferenceQueue class, which is used to save the reference of the recycled object. When soft reference, weak reference and reference queue are used together, the system will add the reference corresponding to the recycled object to the associated reference queue after recycling the referenced object. Before the object is released, the virtual reference corresponding to it will be added to its associated reference queue, so that some necessary measures can be taken before the object is recycled.
ReferenceQueue queue = new ReferenceQueue(); SoftReference ref = new SoftReference(aMyObject, queue);
Unlike soft and weak references, virtual references must be used with reference queues.
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>(); PhantomReference sf = new PhantomReference<>(obj,referenceQueue);
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 in order to be compatible with C.
- Java implements cross platform features through virtual machines, but C + + depends on a specific platform.
- Java has no pointers. 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 garbage collection.
- Java does not support multiple inheritance and can only achieve the same purpose by implementing multiple interfaces, while C + + supports multiple inheritance.
- Java does not support operator overloading. Although addition can be supported for two String objects, it is a built-in operation supported by the language and does not belong to operator overloading, but C + + can.
- Goto in Java is a reserved word, but it is not available. C + + can use goto.
- Java does not support conditional compilation. C + + implements conditional compilation through #ifdef #ifndef and other preprocessing commands.
Little knowledge
What data types should be used in Java to represent prices?
If you are not particularly concerned about memory and performance, use BigDecimal, otherwise use the double type of predefined precision.
How to convert byte to String?
The constructor of String receiving byte [] parameter can be used for conversion. Note that the correct code should be used. Otherwise, the platform default code will be used. This code may be the same as or different from the original code.
How to convert bytes to long type in Java?
String the constructor that receives bytes is converted to string, and then Long.parseLong
Can we cast int to a byte variable? What happens if the value is greater than the range of byte type?
Yes, we can do coercion, but in Java, int is 32 bits and byte is 8 bits. Therefore, if the coercion is, the top 24 bits of int type will be discarded, and the range of byte type is - 128 to 127.
There are two classes, B inherits A and C inherits B. can we convert B to C? Such as C= © B;
Yes, downward transformation. However, it is not recommended and is prone to type transformation exceptions
Which class contains the clone method? Cloneable or Object?
Java.lang.clonable is a symbolic interface and does not contain any methods. The clone method is defined in the object class. And you need to know that the clone() method is a local method, which means that it is implemented in c or c + + or other local languages.
Are + + operators thread safe in Java?
Is not a thread safe operation. It involves multiple instructions, such as reading variable values, increasing, and then storing them back to memory. This process may lead to multiple threads crossing. There will also be race conditions (read modify write).
A = difference between a + B and a += b
+=Implicitly cast the result type of addition operation to the type of holding result. If two integers are added, such as byte, short, or int, they are first promoted to the int type, and then the addition operation is performed.
byte a = 127; byte b = 127; b = a + b; // error : cannot convert from int to byte b += a; // ok
(because a+b operation will promote a and b to int type, assigning int type to byte will cause compilation error)
Can I assign a double value to a variable of type long without casting?
No, you can't assign a double value to a variable of long type without cast, because the range of double type is wider than that of long type, so cast must be performed.
3 * 0.1 = = 0.3 what will be returned? true or false?
false, because some floating-point numbers cannot be expressed exactly.
Which uses more memory, int or Integer?
Integer objects take up more memory. Integer is an object and needs to store the metadata of the object. But int is a primitive type of data, so it takes less space.
Why is String immutable in Java?
String in Java is immutable because Java designers think that strings are used very frequently. Setting strings to immutable allows multiple clients to share the same string. See the answer for more details.
Can we use String in Switch?
Starting with Java 7, we can use strings in switch case, but this is just a syntax sugar. The internal implementation uses the hash code of the string in the switch.
What is the constructor chain in Java?
When you call another constructor from a constructor, it is the constructor chain in Java. This happens only when the constructor of the class is overloaded.
Enumeration class
In JDK1.5, the constructor needs to be called once for each enumerated value
What is an immutable object? How to create an immutable object in Java?
Immutable object means that once an object is created, its state cannot be changed. Any modification creates a new object, such as String, Integer, and other wrapper classes.
How to write Immutable classes in Java?
To write such a class, you need to follow the following principles:
1) The state of immutable object cannot be changed after it is created. Any change to it should produce a new object.
2) All properties of immutable class should be final.
3) Objects must be created correctly. For example, object references cannot be leaked during object creation.
4) The object should be final to restrict the subclass from inheriting the parent class, so as to avoid the subclass changing the immutable attribute of the parent class.
5) If the class contains mutable class objects, a copy of the object is returned to the client instead of the object itself (this article can be classified as a special case in the first article)
Can we create an immutable object that contains a mutable object?
Yes, we can create an immutable object containing a variable object. You just need to be careful not to share the reference of the variable object. If you need to change, return a copy of the original object. The most common example is that an object contains a reference to a date object.
Is it possible that two unequal objects have the same hashcode?
It is possible that two unequal objects may have the same hashcode value, which is why there are conflicts in hashmap. The provision of equal hashcode value only means that if two objects are equal, they must have the same hashcode value, but there is no provision for unequal objects.
Will two identical objects have different hash code s?
No, according to the hash code, this is impossible.
Can we use random numbers in hashcode()?
No, because the hashcode value of the object must be the same.
What is the difference between Comparator and Comparable in Java?
The Comparable interface is used to define the natural order of objects, while the comparator is usually used to define the order customized by the user. There is always only one Comparable, but there can be multiple comparators to define the order of objects.
Why do you need to override the hashCode method when overriding the equals method?
Because the mandatory specification specifies that hashcode and equal methods need to be overridden at the same time, many container classes, such as HashMap and HashSet, depend on the provisions of hashcode and equals.
What's the difference between "a==b" and "a.equals(b)"?
If both a and B are objects, a==b is the reference to compare the two objects. true will be returned only when a and B point to the same object in the heap, while a.equals(b) is for logical comparison. Therefore, it is usually necessary to rewrite this method to provide logical consistency comparison. For example, the String class overrides the equals() method, so it can be used for a comparison of two different objects that contain the same letters.
a. What's the use of hashcode()? What does it have to do with a.equals(b)?
Introduction: the hashCode() method is the hash value of the corresponding object integer. It is commonly used in hash based collection classes, such as Hashtable, HashMap, LinkedHashMap, and so on. It is particularly relevant to the equals() method. According to the Java specification, two objects that use the equal() method to determine equality must have the same hash code.
1. The role of hashcode
List and Set, how to ensure that the Set is not repeated? The equals method is used iteratively to judge that the small amount of data is acceptable, but how to solve the large amount of data? Hashcode is introduced. In fact, the role of hashcode is addressing, which greatly reduces the number of query matches.
2. Is hashcode important
For arrays, lists and collections, it is a burden. For HashMap, HashSet and hashtable, they are extremely important.
3. Principles followed by the equals method
- Symmetry if x.equals(y)true, then y.equals(x)true
- Reflexivity x.equals(x) must be true
- Transitivity if x.equals (y) is true and y.equals (z) is true, then x.equals(z) must be true
- Consistency as long as the contents of X and Y remain the same, no matter how many times you call, the result remains the same
- Other x.equals(null) is always false, and x.equals (different from X data type) is always false
What are the differences between final, finalize and finally?
- Final is a modifier that modifies variables, methods, and classes. If final modifies a variable, it means that the value of the variable cannot be changed after initialization.
- Java technology allows you to use the finalize() method to do the necessary cleanup before the garbage collector clears the object from memory. This method is called by the garbage collector when it determines that the object is not referenced, but when to call finalize is not guaranteed.
- finally is a keyword used for exception handling together with try and catch. finally, the block must be executed regardless of whether an exception occurs in the try block.
What are compile time constants in Java? What are the risks of using it?
Variables are what we call compile time constants. Public here is optional. In fact, these variables are replaced at compile time because the compiler knows the values of these variables and that they cannot be changed at run time. A problem with this method is that you use a public compile time constant in an internal or third-party library, but this value has been changed by others, but your client is still using the old value, and even you have deployed a new JAR. To avoid this, be sure to recompile your program when updating dependent JAR files.
What is the difference between static inner classes and top-level classes?
The source file name of a public top-level class is the same as the class name, which is not required for nested static classes. A nested class is located inside the top-level class. You need to use the name of the top-level class to reference the nested static class. For example, HashMap.Entry is a nested static class, HashMap is a top-level class, and Entry is a nested static class.
What is the difference between Serializable and Externalizable in Java?
Serializable interface is an interface for serializing Java classes so that they can be transmitted on the network or their state can be saved on disk. It is the default serialization method embedded in the JVM. It is costly, fragile and unsafe. Externalizable allows you to control the whole serialization process, specify specific binary format and increase security mechanism.
Name three new features in JDK 1.7?
Although JDK 1.7 is not as large as JDK 5 and 8, it still has many new features, such as try with resource statement, so you don't need to close manually when using streams or resources, and Java will close automatically. Fork join pool implements map reduce in Java to some extent. Allow String variables and text in a Switch. The diamond operator (< >) is used for generic inference. It is no longer necessary to declare generics on the right of variable declaration, so it can write more readable and concise code. Another feature worth mentioning is improved exception handling, such as allowing multiple exceptions to be caught in the same catch block.
Name five new features introduced by JDK 1.8?
Java 8 is an innovative version in the history of Java. The following five main features of JDK 8 are: Lambda expression, which allows anonymous function Stream API to be passed like an object, makes full use of modern multi-core CPU, and can write very simple code Date and Time API. Finally, there is a stable and simple Date and time library for you to use extension methods. Now, There can be static and default methods in the interface. Repeat annotation. Now you can use the same annotation on the same type multiple times.
The following contains the design principles of SOLID in the Java interview process, OOP basis, such as class, object, interface, inheritance, polymorphism, encapsulation, abstraction and some higher-level concepts, such as composition, aggregation and association. It also includes the problem of GOF design pattern.
What is the interface? Why use interfaces instead of concrete classes?
Interfaces are used to define API s. It defines the rules that a class must follow. At the same time, it provides an abstraction, because the client only uses the interface, so there can be multiple implementations, such as the List interface. You can use the ArrayList that can be accessed randomly or the LinkedList that can be easily inserted and deleted. Ordinary methods are not allowed in the interface to ensure abstraction, but in Java 8, you can declare static methods and default ordinary methods in the interface.
What is the difference between abstract classes and interfaces in Java?
There are many differences between abstract classes and interfaces in Java, but the most important one is that Java restricts a class to inherit only one class, but can implement multiple interfaces. Abstract classes can well define the default behavior of a family class, and interfaces can better define types, which is helpful to realize the polymorphism mechanism later. See article 6.
What are the common methods of Object?
Clone equals hashcode wait notify notify all finalize toString getClass are public methods except clone and finalize.
Of the 11 methods, wait was overloaded twice
The difference between equals and = =
Difference 1. = = is an operator and equals is a method of Object class
Difference 2. Difference in comparison
- For variable comparison of basic types: = = used to compare whether the values are equal. equals cannot be directly used for the comparison of basic data types. It needs to be converted to its corresponding packaging type.
- When used for comparison of reference types== Both and equals compare whether the addresses in the stack memory are equal. Equal is true, otherwise false. However, the equals method is usually overridden to compare the contents of objects.
Differences between String, StringBuffer and StringBuilder
First point: variable and scope of application. String objects are immutable, while StringBuffer and StringBuilder are variable character sequences. Each operation on string is equivalent to generating a new string object, while the operations on StringBuffer and StringBuilder are operations on the object itself and will not generate new objects. Therefore, avoid using string for strings with frequent content changes, because frequent object generation will affect the system performance.
Second point: thread safety. String is immutable because of its final modification. Its security is simple and pure. The difference between StringBuilder and StringBuffer is that StringBuilder does not guarantee synchronization, that is, if you need thread safety, you need to use StringBuffer. StringBuilder without synchronization is more efficient.
Can switch use String as a parameter
Java 1.7 began to support it, but it is actually a Java syntax sugar. In addition, byte, short, int and enumeration can be used for switch, while boolean and floating-point types cannot.
Interface and abstract class
- A subclass can only inherit one abstract class, but can implement multiple interfaces
- Abstract classes can have constructors, while interfaces have no constructors
- Abstract classes can have ordinary member variables, while interfaces have no ordinary member variables
- Abstract classes and interfaces can have static member variables. The access types of static member variables in abstract classes are arbitrary, and interfaces can only be public static final (default)
- Abstract classes can have no abstract methods, abstract classes can have ordinary methods, and interfaces are all abstract methods
- Abstract classes can have static methods, and interfaces cannot have static methods
- Methods in abstract classes can be public and protected; Interface methods only have public abstract
Abstract class and final class
Abstract classes can have no abstract methods, and final classes can have no final methods
The final class cannot be inherited, and the final method cannot be overridden (can be overloaded)
abnormal
Related keywords throw, throws, try... catch, finally
- throws is used on the method signature so that the exception thrown can be handled by the caller
- Throw method throws an exception through throw
- try is used to detect the enclosed statement block. If there is an exception, the catch clause captures and executes the catch block
About finally
- finally, no matter whether there is an exception or not, it should be handled
- When there is a return in try and catch, finally will still execute. Finally will execute before return
- Regardless of any exception thrown, finally execute before return
- Finally, it is executed after the expression operation after return (at this time, the calculated value is not returned, but the value to be returned is saved first. Regardless of the code in finally, the returned value will not change, and it is still the previously saved value). Therefore, the return value of the function is determined before finally execution
Note: it is better not to include return in finally, otherwise the program will exit in advance, and the return value is not the return value saved in try or catch
finally, there are several situations where the program does not execute: early termination, such as calling System.exit, virus, power failure
Checked exceptions and runtime exceptions
- Checked exceptions must be caught by the try... catch statement block or declared in the method signature through the throws clause. The Checked Exception must be caught and handled during compilation. It is named Checked Exception because the java compiler and the Java virtual machine need to check to ensure that this rule is observed.
Common checked exceptions: classnotfoundexception IOException FileNotFoundException eofexception
- For runtime exceptions, the programmer needs to analyze the code and decide whether to capture and handle them. For example, null pointers are divided by 0
Common runtime exceptions: NullPointerException arithmeticexception ClassCastException illegalargumentexception IllegalStateException indexoutofboundsexception NoSuchElementException
- Error is a serious error, such as system crash, virtual machine error, dynamic link failure, etc. these errors cannot be recovered or cannot be captured, which will lead to application interruption. Error does not need to be captured.
super appears in the subclass of the parent class. There are three ways to exist
- super.xxx(xxx is the variable name or object name) means to obtain the variable or reference of XXX in the parent class
- super.xxx(); (xxx is the method name) means to directly access and call the method in the parent class
- super() calls the parent class construction
Note: super can only refer to its direct parent class
The difference between this () & Super () in construction method
- The call to super() must be written in the first line of the subclass construction method, otherwise the compilation will not pass
- super calls the parent class from a subclass. this calls other constructs in the same class and needs to be placed in the first row.
- Although you can call one constructor with this, you cannot call two
- this and super cannot appear in the same constructor, otherwise the compilation will not pass
- this() and super() refer to objects that cannot be used in static environments
- In essence, this is a pointer to this object. super is a keyword
Construct inner class and static inner class objects
public class Enclosingone { public class Insideone {} public static class Insideone{} } public class Test { public static void main(String[] args) { // Constructing an internal class object requires a reference to an external class Enclosingone.Insideone obj1 = new Enclosingone().new Insideone(); // Objects that construct static inner classes Enclosingone.Insideone obj2 = new Enclosingone.Insideone(); } }
Static inner classes do not need to have references to outer classes. However, non static internal classes need to hold references to external classes. Non static inner classes can access static and non static members of external classes. Static inner classes cannot access non static members of external classes, but only static members of external classes.
serialize
Data declared as static and transient types cannot be serialized. Deserialization requires a parameterless constructor
Java shift operator
There are three shift operators in java
- < <: shift left operator, x < < 1, which is equivalent to x multiplied by 2 (without overflow), and the low order is supplemented by 0
- >>: shift right with sign, x > > 1, which is equivalent to x divided by 2, positive high complement 0, negative high complement 1
- >>>: move unsigned right, ignore the sign bit, and fill up the empty bits with 0
Formal & argument
Formal parameters can be regarded as local variables. Formal parameters, like local variables, cannot leave methods. It is used only in the method and is not visible outside the method. Formal parameters can only use the final modifier, and any other modifier will cause compiler errors. However, there is a certain limitation to using this modifier, that is, no modification can be made to the parameters in the method. However, in general, the formal parameters of a method do not need final modification. Only in special cases, that is: Method inner classes. If the internal class in a method uses the parameter or local variable of the method, the parameter or local variable should be final. The value of the formal parameter is changed according to the caller when calling, and the actual parameter changes the value of the formal parameter with its own value (pointers and references are in this column), that is, the actual parameter is passed.
Why should local variables be initialized
Local variables refer to variables in class methods and must be initialized. Local variables are allocated to the stack at runtime, with large amount and short life cycle. If the virtual machine initializes each local variable, it will be a great overhead, but it is unsafe to use the variable without initializing it to the default value. For the comprehensive consideration of speed and security, the solution is that the virtual machine is not initialized, but the writer must assign a value to the variable before use.
Robustness of Java language
When compiling and running programs, Java should check for possible problems to eliminate errors. It provides automatic garbage collection for memory management to prevent programmers from making errors when managing memory. Through the integrated object-oriented exception handling mechanism, Java reveals possible but unhandled exceptions at compile time to help programmers make correct choices to prevent system crash. In addition, Java can catch many common errors in type declarations at compile time to prevent dynamic runtime mismatch problems.
Sorting algorithm complexity
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-od76rsur-1633419301780) (/ users / xuzhiming / library / Application Support / typora user images / image-20210807093105527. PNG)]
Intelligence problem
There are eight coins, one is light and seven are heavy. You can only weigh them twice with the Libra, so you can calculate the light?
First, divide the coin into two parts, take one from each of the two parts, and then weigh the two parts respectively. If the two parts weigh the same, weigh the two taken out and work out the result. If the weight of the two parts is different, take out the lighter one and weigh the remaining two. If the weight is the same, the one taken out is light. If it is different, the light one is light.
OutOfBoundsException NoSuchElementException
- Error is a serious error, such as system crash, virtual machine error, dynamic link failure, etc. these errors cannot be recovered or cannot be captured, which will lead to application interruption. Error does not need to be captured.
super appears in the subclass of the parent class. There are three ways to exist
- super.xxx(xxx is the variable name or object name) means to obtain the variable or reference of XXX in the parent class
- super.xxx(); (xxx is the method name) means to directly access and call the method in the parent class
- super() calls the parent class construction
Note: super can only refer to its direct parent class
The difference between this () & Super () in construction method
- The call to super() must be written in the first line of the subclass construction method, otherwise the compilation will not pass
- super calls the parent class from a subclass. this calls other constructs in the same class and needs to be placed in the first row.
- Although you can call one constructor with this, you cannot call two
- this and super cannot appear in the same constructor, otherwise the compilation will not pass
- this() and super() refer to objects that cannot be used in static environments
- In essence, this is a pointer to this object. super is a keyword
Construct inner class and static inner class objects
public class Enclosingone { public class Insideone {} public static class Insideone{} } public class Test { public static void main(String[] args) { // Constructing an internal class object requires a reference to an external class Enclosingone.Insideone obj1 = new Enclosingone().new Insideone(); // Objects that construct static inner classes Enclosingone.Insideone obj2 = new Enclosingone.Insideone(); } }
Static inner classes do not need to have references to outer classes. However, non static internal classes need to hold references to external classes. Non static inner classes can access static and non static members of external classes. Static inner classes cannot access non static members of external classes, but only static members of external classes.
serialize
Data declared as static and transient types cannot be serialized. Deserialization requires a parameterless constructor
Java shift operator
There are three shift operators in java
- < <: shift left operator, x < < 1, which is equivalent to x multiplied by 2 (without overflow), and the low order is supplemented by 0
- >>: shift right with sign, x > > 1, which is equivalent to x divided by 2, positive high complement 0, negative high complement 1
- >>>: move unsigned right, ignore the sign bit, and fill up the empty bits with 0
Formal & argument
Formal parameters can be regarded as local variables. Formal parameters, like local variables, cannot leave methods. It is used only in the method and is not visible outside the method. Formal parameters can only use the final modifier, and any other modifier will cause compiler errors. However, there is a certain limitation to using this modifier, that is, no modification can be made to the parameters in the method. However, in general, the formal parameters of a method do not need final modification. Only in special cases, that is: Method inner classes. If the internal class in a method uses the parameter or local variable of the method, the parameter or local variable should be final. The value of the formal parameter is changed according to the caller when calling, and the actual parameter changes the value of the formal parameter with its own value (pointers and references are in this column), that is, the actual parameter is passed.
Why should local variables be initialized
Local variables refer to variables in class methods and must be initialized. Local variables are allocated to the stack at runtime, with large amount and short life cycle. If the virtual machine initializes each local variable, it will be a great overhead, but it is unsafe to use the variable without initializing it to the default value. For the comprehensive consideration of speed and security, the solution is that the virtual machine is not initialized, but the writer must assign a value to the variable before use.
Robustness of Java language
When compiling and running programs, Java should check for possible problems to eliminate errors. It provides automatic garbage collection for memory management to prevent programmers from making errors when managing memory. Through the integrated object-oriented exception handling mechanism, Java reveals possible but unhandled exceptions at compile time to help programmers make correct choices to prevent system crash. In addition, Java can catch many common errors in type declarations at compile time to prevent dynamic runtime mismatch problems.
Sorting algorithm complexity
[external chain picture transferring... (img-Od76rSUR-1633419301780)]
Intelligence problem
There are eight coins, one is light and seven are heavy. You can only weigh them twice with the Libra, so you can calculate the light?
First, divide the coin into two parts, take one from each of the two parts, and then weigh the two parts respectively. If the two parts weigh the same, weigh the two taken out and work out the result. If the weight of the two parts is different, take out the lighter one and weigh the remaining two. If the weight is the same, the one taken out is light. If it is different, the light one is light.