Hey guys, it’s the interview season and Cxuan is going to rewrite the interview questions related to Java. Let’s start with the basics. These questions belong to the basic series and do not include the questions related to multithreading and JVM.
Java based article
What are the features of Java
concurrency
You can execute many statements in it without having to execute it all at onceobject-oriented
: class-based and object-oriented programming languages.The independence of
Support:Write it once, run it anywhereThat is, compiled code can run on all platforms that support Java.
The characteristics of Java
Java has the following features
simple
Java makes your life a lot easier by focusing on the main business logic and not on Pointers, operator overloading, memory reclamation, and other functions that are irrelevant to the main business.portability
Java is platform independent, which means that any application written on one platform can be easily ported to another.security
, which converts all the code into bytecode, unreadable by humans. It makes it possible to develop virus-free, tamper-free systems/applications.dynamic
It has the ability to adapt to changing environments, and it can support dynamic memory allocation, thus reducing memory waste and improving application performance.distributed
Java provides functionality to help create distributed applications. useRemote Method Invocation (RMI)
A program can call another program’s methods over the network and get the output. You can access files by calling methods from any computer on the Internet. This is a revolutionary feature, too important for today’s Internet.Robustness,
Java has powerful memory management capabilities to check code at compile and run time, which helps eliminate errors.A high performance
Java’s darkest technology is bytecode programming. Java code is compiled into bytecode that can be easily converted into local machine code. High performance through JIT just-in-time compiler.explanatory
Java is compiled into bytecode and interpreted by the Java runtime environment.Multithreaded sex
Java supports multiple threads of execution (also known as lightweight processes), including a set of synchronization primitives. This makes it easier to program with threads, and Java implements thread-safety through the pipe-side model.
What are the characteristics of object orientation
There are three main characteristics of object orientation
-
Encapsulation: Encapsulation is one of the characteristics of object orientation and is the main feature of object and class concepts. Encapsulation is to encapsulate objective things into abstract classes, and classes can only allow their data and methods to be operated by trusted classes or objects, to hide the information of the untrusted.
-
Inheritance: Inheritance refers to using all the functionality of an existing class and extending those functionality without having to rewrite the original class.
-
Polymorphism: Polymorphism is a technique that allows you to set a parent object to be equal to one or more of its children. Once assigned, the parent object can behave differently depending on the properties of the children currently assigned to it. It is possible to assign a pointer of a subclass type to a pointer of a superclass type.
What is the difference between the JDK and the JRE
- The English name of JRE is Java Runtime Environment. It mainly consists of two parts, the standard implementation of the JVM and some basic class libraries for Java. What it has over the JVM is a portion of the Java class library.
- The JDK is known as the Java Development Kit. The JDK is the core of Java development, integrating the JRE and some handy gadgets. For example, javac.exe, java.exe, jar.
What is a JVM
- The JVM is a Java Virtual Machine. The Java virtual machine is the heart of a cross-platform implementation
Roughly speaking, the relationship between JRE, JDK, and JVM is as follows
Describe the difference between value passing and reference passing
To really understand, you can refer to this article: www.zhihu.com/question/31…
In simple terms
Value passing refers to making a copy of the actual arguments to the function when it is called, so that if the function modifies the formal arguments it passes, the actual arguments will not be affected
Reference passing refers to passing the address of an object directly into a function when it is called. If formal parameters are modified, the actual parameter values will be affected.
What is the difference between equals and ==
== is a Java operator that can be compared in two ways
- for
Basic data types
In terms of, == = judge both sidesvalue
Are equal
public class DoubleCompareAndEquals {
Person person1 = new Person(24."boy");
Person person2 = new Person(24."girl");
int c = 10;
private void doubleCompare(a){
int a = 10;
int b = 10; System.out.println(a == b); System.out.println(a == c); System.out.println(person1.getId() == person2.getId()); }}Copy the code
- for
Reference types
In terms of, == = judge both sidesreference
Equality, that is, to determine whether two objects refer to the same memory region.
private void equals(a){
System.out.println(person1.getName().equals(person2.getName()));
}
Copy the code
Equals is the parent of all objects in Java, a method defined by the Object class. It can only compare objects, and it indicates whether the values of both references are equal. So remember, equals doesn’t compare references to equals, equals equals to values.
Equals as a comparison between objects has the following properties
reflexivity
For any non-empty reference to x, x.equals(x) should return true.symmetry
: For any non-empty reference x and y, if x.evers (y) is true, then y.evers (x) is also true.transitivity
: For any non-null reference value, there are three values, x, y, and z. If x.quals (y) returns true and y.quals (z) returns true, then x.quals (z) should return true as well.consistency
: For any non-empty reference x and y, x.equals(y) must always be equal if they are equal.Non empty
: for any non-null reference value x, x.equals(null) must return false.
What are the basic data types in Java and how many bytes they occupy
In Java, there are only four types and eight types of data types
- Integer types: byte, short, int, and long
Byte is a byte. 1 byte equals 8 bits. The default byte value is 0.
Short takes up two bytes (16 bits). 1 short = 16 bits, which also defaults to 0.
1 int = 32 bits, default is 0;
Long takes up eight bytes, that is, 64 bits, 1 long = 64 bits, default is 0L;
So the size of the integer is long > int > short > byte
- floating-point
Floating-point types have two data types: float and double
1 float = 32 bits. The default value is 0.0f.
1 double = 64 bits. Default value: 0.0d;
- character
The char type is a single 16-bit Unicode character with a minimum value of \u0000 (0) and a maximum value of \ uFFFF (65535). The char data type can store any character, such as char A = ‘a’.
- The Boolean
Boolean refers to Boolean. Boolean has only two values, true or false, representing only one bit. The default value is false.
The above X bits refer to the memory usage.
How is equals overridden in String
String represents a String in Java. The String class is special in that its entire class is final. That is, a String cannot be inherited by any class.
Equals is defined by Object. Object is the parent of all classes, including String. String overrides equals
- It first determines the two strings to be compared and their values
reference
Is it equal? Return true if the reference is equal. If not, continue - If the object is not an instance of String, return false. If so, compare the two strings to see if they are equal in length. If the length is the same, each of the strings is compared
character
If a character is not equal, false is returned.
Here’s a flow chart
Here’s another reminder, you might be wondering when
if (this == anObject) {
return true;
}
Copy the code
How does this statement return true? Strings compare heap space and, on first glance, seem to never walk, but you forgot that the string.intern () method represents concepts that differ between JDK versions
In JDK1.7 and later, the intern method is called to determine whether the specified string exists in the runtime constant pool, and if not, to add the string to the constant pool and return the object in the constant pool.
The verification process is as follows
private void StringOverrideEquals(a){
String s1 = "aaa";
String s2 = "aa" + new String("a");
String s3 = new String("aaa");
System.out.println(s1.intern().equals(s1));
System.out.println(s1.intern().equals(s2));
System.out.println(s3.intern().equals(s1));
}
Copy the code
-
First, s1.intern. Equals (s1) returns true anyway, because the s1 string already exists in the constant pool when created.
-
Then the second statement returns false because S1 returns objects from the constant pool, while S2 returns objects from the heap
-
The third statement, s3.intern. Equals (s1), returns true because the S3 object creates an object in the heap, but “aaa” in S3 returns objects in the constant pool.
Why do I have to override hashCode to override equals
The equals method and hashCode are both methods defined in Object and are often overridden together.
The equals method is used to compare whether objects are equal in size, and the Hashcode method is used to determine the hash value of each object. Overwriting equals without overwriting hashcode is likely to result in two different objects with equal Hashcodes, causing a conflict. Such as
String str1 = "Call";
String str2 = "Important";
Copy the code
Hashcode is equal to hashCode, but not equals.
Let’s look at the official definition of hashCode
To sum it up
- If you call the hashCode method on the same object during Java runtime, you should always return the same hashCode no matter how many times you call it, but executing the hashCode method may not return the same value across different Java programs.
- If two objects have equal equals, then hashCode must be the same
- If two objects are not equal to equals, then hashCode may also be the same, so you need to rewrite hashCode because you don’t know the underlying structure of hashCode, so you need to rewrite hashCode, To generate different hashCode values for different objects, which improves access speed for different objects.
- HashCode is usually implemented by converting addresses to integers.
Two objects have the same hashcode, so equals must also be true
For a very simple example, if you override the hashcode method to take the remainder, the hashcode of two objects may be the same, but their equals may not be the same.
Even if you don’t rewrite the HashCode method, LET me give you a code example
String str1 = "Call";
String str2 = "Important";
System. out. println(String. format("| str2 str1: % d: % d", str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));
Copy the code
The output of the above two pieces of code is
Str1:1179395 | str2:1179395 false
These two strings do not have the same equals. That is, even if hashCode is the same string, equals may be different.
String s1 = new String(” ABC “) creates several objects in memory
One or two, String s1 is declaring a String s1 variable, it’s not an object. Using the new keyword creates one object in the heap, and the other object is ABC, which is created in the constant pool, so there are two objects created; If ABC already exists in the constant pool, an object will be created.
Check out another of my articles on String, StringBuffer, and StringBuilder
Why strings are immutable, how strings are defined in the JDK source code, and why they are designed this way.
An immutable object is an object whose internal state cannot be changed once it is created. In other words, immutable objects need to follow the following principles
- All internal properties of immutable objects are final
- The internal properties of immutable objects are private
- Immutable objects cannot provide any methods to modify internal state, nor can setter methods
- Immutable objects cannot be inherited or extended
Instead of asking why strings are immutable, ask how strings are designed to be immutable.
The String class is an object that exists independently of the Basic Java data types. A String you can think of as a collection of strings. Strings are designed to be final, meaning that once a String object is created, its value cannot be modified. Any way to modify a String value is to recreate a String. The String object is created in the runtime constant pool, which is part of the method area and moved to the heap in JDK1.7.
Immutable objects are not really immutable, and their internal properties and values can be modified by reflection, but we generally don’t do this.
What is the static keyword for? Talk about your understanding
Static is an important keyword in Java. The concept of static is static. In Java, static is used mainly
- Modifies variables. Static modifies variables called
A static variable
, also known asClass variables
Class variables are owned by the class. For different classes, there is only one static variable. Static variables are modified in the method section. Static modified variables can be passed directlyClass name. Variable nameInstead of instantiating the class and using it again. - Modifier methods, static modifier methods are called
A static method
Static methods can pass directly throughClass name. Method nameYou cannot use non-static properties and methods inside static methods - Static can modify a block of code. There are two main types of static. One is defined directly in a class
static{}
This is calledStatic code block
One is to define it in a classStatic inner class
, the use ofstatic class xxx
To define it. - Static can be used to guide static packets by using
import static xxx
This method is generally not recommended - Static can be used in conjunction with the singleton pattern to implement thread-safe singleton patterns by double-checking locks.
A little static can still impress me?
What is the final keyword for? Talk about your understanding
Final is a Java keyword that means immutable. In Java, final is mainly used
- Modifier class, final modifier class cannot be inherited, cannot be inherited means cannot be used
extends
To inherit classes that are modified by final. - Final modified variables cannot be overwritten. There are two meanings that cannot be overwritten. For basic data types, the value of a final modified variable cannot be changed, and the reference of a final modified object cannot be changed, but the properties inside the object can be modified. The final variable does this to some extent
immutable
As a result, it can be used to protect read-only data, especially in concurrent programming, because final variables can explicitly no longer be assigned, helping to reduce additional synchronization overhead. - Modifier methods, final modifier methods cannot be overridden.
- Final modifiers are not necessarily related to Java program performance optimization
What is the difference between abstract classes and interfaces
Abstract classes and interfaces are keywords in Java that allow methods to be defined without concrete method implementation. Both abstract classes and interfaces are allowed to be inherited, and they are widely used in JDK and framework source code to implement polymorphism and different design patterns.
The difference is that
Different levels of abstraction
There are three levels of abstraction: class, abstract class, and interface. The degree of abstraction is interface > Abstract class > class. In the interface, only method definition is allowed, method implementation is not allowed, method definition and implementation can be carried out in abstract class; A class is only allowed to implement a method, and the definition of a method IS not allowed to appear after a method{}
Different keywords are used
Use: classclass
To represent; Abstract class usageabstract class
To represent; Interface to useinterface
To represent thevariable
Variables defined in an interface can only be public static constants. Variables in an abstract class are ordinary variables.
The difference between overwriting and overloading
In Java, overwriting and overloading are different representations of the same method, so let’s make a simple distinction between overwriting and overloading
The relationship between father and son is different
Overrides are different representations of children and parents, while overrides are different representations in the same class;The concept of different
, the subclass overrides the parent class method commonly used@override
To represent; The method declaration, parameter type and order of the overwritten method must be exactly the same as the parent class. Overloading is a concept in the same class that requires overloaded methods to meet any of the following requirements: the order of method arguments, the number of arguments, and the type of any of the arguments should remain different.
Can the constructor be overridden, can it be overridden?
This problem tests your understanding and knowledge of constructors.
When we create an object in Java, we call its constructor, as in the following code
InstanceObject IO = new InstanceObject() ; // Call the no-argument constructor
InstanceObject IO = new InstanceObject(xxx) ; // call the constructor with arguments
Copy the code
What is the concept of overloading?
It means that we can define methods with the same name, distinguish them by defining different input parameters, and then when we call them, the JVM will choose the appropriate method to execute based on the different parameter styles.
That is, the concept of overloading is more about different descriptions of methods with the same name. So this code is obviously overloaded, because it has the same name, and I can call different constructors to initialize with or without arguments.
So can the constructor be overridden? So let’s first look at what is rewrite
Overrides are subclasses that rewrite the implementation of the parent class’s accessible methods without changing either the return value or the parameter. From the definition of overrides we know that the constructor cannot be overridden.
First, the constructor returns no value, and second, the constructor name must be the same as the class name.
You can’t write public A() in class A; Let’s also write public A() in class B, which obviously won’t compile.
What is the range of byte? How do you calculate it
The byte value ranges from -128 to 127. There are 256 bytes in total. A byte takes up one byte on the computer, so that is 8 bits, so the maximum is 2^7 = 1111 1111.
In Java, complement is used to represent binary numbers. The highest bit of complement is the sign bit, the highest bit is 0 for the positive number, and the highest bit is 1 for the negative number. The complement of a positive number is itself. The maximum negative number is 1111, 1111, which involves two zeros, a +0 and a -0. +0 is a positive number, which is 0, and -0 is a negative number, which is -128, so the byte range is -128-127.
Difference between HashMap and HashTable
The same
Both HashMap and HashTable are implemented based on hash tables, where each element is a key-value pair. Both HashMap and HashTable implement the Map, Cloneable, and Serializable interfaces.
The difference between
- Different parent class: HashMap inherits
AbstractMap
Class, which HashTable inheritsDictionary
类
- Empty values are different: HashMap allows empty keys and values, HashTable does not. A HashMap treats a Null key as a normal key. Null key duplication is not allowed.
- Thread-safe: A HashMap is not thread-safe. If multiple external operations modify the HashMap data structure at the same time, such as add or DELETE, synchronization must be performed. Changes to a key or value alone are not changes to the data structure. You can choose to construct a thread-safe Map for example
Collections.synchronizedMap
Or is itConcurrentHashMap
. And HashTable itself is a thread-safe container. - Performance: Although HashMap and HashTable are both based
Singly linked lists
However, HashMap performs put or get operations, which can achieve constant time performance. The put and get operations on HashTable are addedsynchronized
It’s locked, so it’s inefficient.
- The initial size is different: the initial size of a HashTable is 11, and the size of each subsequent expansion is 2n+1 (n is the length of the previous expansion). The initial size of a HashMap is 16, and each subsequent expansion is twice that size. When created, if given an initial capacity value, the HashTable will use the size you gave it, and the HashMap will expand it to a power of two.
The difference between HashMap and HashSet
HashSet extends AbstractSet and implements Set, Cloneable, and Java.io.Serializable interfaces. A HashSet does not allow duplicate values in the collection. A HashSet is essentially a HashMap, and all operations on a HashSet are operations on a HashMap. So a HashSet does not guarantee collection order, nor is it a thread-safe container.
The underlying structure of a HashMap
In JDK1.7, HashMap is implemented in bitbuckets and linked lists. That is, linked lists are used to handle conflicts. Lists with the same hash value are stored in an array. However, when there are many elements in a bucket, that is, there are many elements with the same hash value, searching by key value is inefficient.
So, compared to JDK 1.7, JDK 1.8 has some changes in the underlying structure. When the elements in each bucket are greater than 8, it is converted to a red-black tree to optimize query efficiency.
Why is the length of a HashMap a power of 2
I’ve been thinking about this question for a few days. When I asked my group members why length%hash == (n-1) &hash, they said it was equal only if length is a power of 2, And I said, is length not a power of two? Actually, I don’t understand causality, because the length of a HashMap is a power of 2, so I use the remainder to determine the subscript in the bucket. If length is not a power of 2, you can give an example
For example, if the length is 9, 3 & (9-1) = 0, 2 & (9-1) = 0, both on 0, collision;
This increases the chance of HashMap collisions.
HashMap multithreading causes an infinite loop
HashMap is not a thread-safe container. In high-concurrency scenarios, ConcurrentHashMap should be used. Using HashMap in multi-threaded scenarios causes an infinite loop (based on JDK1.7) at the rehash location, i.e
do {
Entry<K,V> next = e.next; // <-- suppose the thread is scheduled to suspend as soon as it reaches this point
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while(e ! =null);
Copy the code
This is a snippet of JDK1.7’s Rehash code that forms loops in concurrent scenarios.
JDK1.8 also causes an infinite loop.
What are the thread-safe implementations of HashMap
Since HashMap is not a thread-safe container, ConcurrentHashMap is recommended for concurrent scenarios, or a thread-safe HashMap, using a thread-safe container under the Collections package, for example
Collections.synchronizedMap(new HashMap());
Copy the code
You can also use HashTable, which is also a thread-safe container based on key-value storage. HashMap is often compared to HashTable because HashTable has the same data structure as HashMap.
The most efficient of the above is ConcurrentHashMap.
Let’s talk about how HashMap Put works
The hash function is first used to compute the key, and then the actual insert method is performed
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
// If the table is null or no memory is allocated for the table, resize the table once
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// The (n-1) &hash is the actual hash in the table
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
// If not empty
else {
Node<K,V> e; K k;
// Calculate the actual hash value in the table compared to the key.hash to be inserted
if(p.hash == hash && ((k = p.key) == key || (key ! =null && key.equals(k))))
e = p;
// If not, and the current node is already on the TreeNode
else if (p instanceof TreeNode)
// Use red-black tree storage mode
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
// key.hash is different and no longer on TreeNode, find p.ext ==null on the linked list
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
Insert at the end of the table
p.next = newNode(hash, key, value, null);
// If the number of new nodes reaches the threshold, enter treeifyBin() to check again
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
// If a node with the same hash and key is found, exit the loop
if(e.hash == hash && ((k = e.key) == key || (key ! =null && key.equals(k))))
break;
// Update p to point to the next nodep = e; }}// Map contains old values, return old values
if(e ! =null) { // existing mapping for key
V oldValue = e.value;
if(! onlyIfAbsent || oldValue ==null)
e.value = value;
afterNodeAccess(e);
returnoldValue; }}// Map adjustment times + 1
++modCount;
// The number of key-value pairs reaches the threshold and needs to be expanded
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
Copy the code
The core of the HashMap PUT method is the putVal method, which is inserted as follows
- It first determines whether the HashMap is newly built, and if so resize first
- Then determine whether the element to be inserted already exists in the HashMap (indicating that there is a collision). If not, directly generate a new K-V node for storage, and then determine whether to expand the capacity.
- If the element to be inserted already exists, a conflict occurs, which is converted to a linked list or red-black tree to resolve the conflict. First, determine whether the hash and key in the linked list are equal. If they are equal, replace the old value with the new value. If the hash and key are not equal and do not belong to the TreeNode type, it will be directly converted to the linked list for traversal. If the next node of the linked list is null, it will determine whether to convert it to a red-black tree. If the next node of the linked list is not null, it will find the node with exactly the same key during traversal. Then replace the old node with the new node
See this article for an in-depth understanding of HashMap, and you’ll have no problem arguing with your interviewer after reading this HashMap
ConcurrentHashMap Underlying implementation
ConcurrentHashMap is a thread-safe Map and is the preferred data structure for high-concurrency scenarios. The underlying ConcurrentHashMap is implemented using segmented locking.
The Integer buffer pool
The Integer cache pool, also known as IntegerCache, is the static inner class of Integer.
The default value is used to cache the numbers between -128-127. If there are numbers between -128-127, new Integer is used to fetch the numbers directly from the cache pool without creating objects. This operation reduces the allocation of objects in the heap and improves the running efficiency of the program.
For example, to create an Integer a = 24, we call valueOf of Integer, which can be obtained by decompilation
And then let’s look at the valueOf method
If it is within the specified cache pool, the cached value is returned without creating a new Integer object.
The size of the cache can use XX: AutoBoxCacheMax to specify, in the VM initialization, Java. Lang. Integer. IntegerCache. High properties will be set up and stored in the sun. The misc. VM system of private property.
Utf-8 and Unicode relationships
Since each country has its own unique character encoding, Unicode was developed to create a new standard for mapping characters in most languages used today, some of which are not necessary, but are essential for creating text. Unicode is a Character Set. A Character Set gives all characters a unique number, but it does not specify how to store them. Different characters have different storage space. Some require only one byte, while others require two, three or four bytes.
Utf-8 is just one of many ways that text characters can be decoded. It is a variable length method. Utf-8 represents the format for 8-bit groups of Unicode characters, using 1-4 bytes to represent characters.
U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+1FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
Copy the code
As you can see, UTF-8 is lengthened by the leading flag bit. Single-byte characters take up only one byte, achieving backwards ASCII compatibility, and can contain all characters in Unicode, as utF-32 does, while reducing the space taken up during storage transfer.
Item utF-8 environment, char C = ‘middle’, whether valid
Yes, because Unicode encodings are 2-byte encodings, UTF-8 is an implementation of Unicode that encods in a variable length character set. Char C = ‘in’ is two bytes, so it can be stored. Legal.
Arrays.aslist What should I pay attention to
Arrays.asList is a static method of Arrays that converts Arrays to lists. Note the following points
- AsList can’t be modified structurally after the conversion of Arrays. What is structured modification? You can’t add or subtract any more elements from the List.
public static void main(String[] args) {
Integer[] integer = new Integer[] { 1.2.3.4 };
List integetList = Arrays.asList(integer);
integetList.add(5);
}
Copy the code
The result will be thrown
Exception in thread "main" java.lang.UnsupportedOperationException
Copy the code
We can find the problem by looking at the source code
// This is the inner class of java.util.Arrays, not java.util.ArrayList
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess.java.io.Serializable
Copy the code
AbstractList inheritance AbstractList throws exceptions directly for add, remove, and set methods. That is, if an inherited subclass does not override these methods, then instances of subclasses calling these methods will throw exceptions directly.
Here is the definition of a method in AbstractList, and we can see the specific exception thrown:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
Copy the code
The set method also throws a field, but because the inner ArrayList class overrides the set method, it supports elements that can be modified.
- Arrays.aslist does not support base type conversions
Basic data types in the Java (byte, short, int, long, float, double, Boolean) is not support the Arrays. AsList method to convert
The difference between Collections and Collections
Collection and Collections are classes that reside under the java.util package
AbstractList, AbstractSet, etc. Abstract class AbstractList, AbstractSet, etc. The Collection class defines only a section of standard methods such as add, remove, set, equals, etc. The concrete methods are implemented by the abstract class or implementation class.
Collections is a utility class for the collection class, and Collections provides some basic uses of the utility classes
- The sort method, which sorts the current collection, and classes that implement the Comparable interface can use only one sort scheme, called natural comparison
- Such as implementing thread-safe containers
Collections.synchronizedList
,Collections.synchronizedMap
等 - Reverse Reverses, using the reverse method to sort a specified list in descending order based on the natural order of the elements.
- Fill replaces all elements in the specified list with the specified element.
The reader can browse through the source code for Collections. Collections cannot be instantiated, so the methods in Collections are defined by Collections. Method directly called.
Do you know fail-fast and Fail-safe
Fail – fast is a kind of rapid failure mechanism in Java, Java, all the collection under the util package is fail fast, fail fast will throw ConcurrentModificationException, You can think of fail-fast as a fast detection mechanism that can only detect errors, not recover from them. Fail-fast doesn’t have to exist only in multithreaded environments. ArrayList will also throw this exception. The main reason is that modCount is not equal to expectedModCount.
Fail-safe is a security failure mechanism in Java. It indicates that the collection is not accessed directly on the original collection. Instead, the original collection content is copied and traversed over the copied collection. As the iteration is to traverse the copies of the original collection, so in the process of traversing the changes to the original collection and cannot be detected by the iterator, so will not trigger a ConcurrentModificationException. Containers under the java.util.concurrent package are securely failed and can be used in multi-threaded conditions and modified concurrently.
The difference between ArrayList, LinkedList, and Vector
This is also a platitude question
ArrayList, LinkedList, and Vector are all utility classes in the java.util package that implement the List interface.
- The underlying layer of an ArrayList is a dynamic array, which is evolved based on the properties of arrays, so an ArrayList is very fast to traverse, but slow to add and delete, because it involves copying arrays. ArrayList is a non-thread-safe container that can cause problems in concurrent scenarios and is recommended if you want to use thread-safe containers
Collections.synchronizedList
; ArrayList increases capacity by 50% when expanded. - The underlying LinkedList is a two-way LinkedList, so linkedlists can be added and deleted very quickly by removing elements and pointing to new elements. But LinkedList traversal is slow, because you only know the value of the next element each time you visit it. LinkedList is also a non-thread-safe container and is recommended
Collections.synchronizedList
- Vector was one of the first collections to appear. Vector is a thread-safe container whose methods are added rudely
synchronized
Lock, so its add and delete, traversal efficiency is very low. When a Vector is expanded, it doubles in size.
What is the difference between Exception and Error
Exception is an Exception that occurs during compilation and uncheckedException that occurs during program execution. IOException is a common checkedException, uncheckedException is called RuntimeException, Common RuntimeException mainly NullPointerException, IllegalArgumentException, ArrayIndexOutofBoundException, etc., the Exception can be caught.
Error refers to an Error that occurs during the running of a program. Usually, the program crashes. Error is usually unrecoverable and cannot be captured.
You can refer to this article for details. After reading the Exception and Error, you will have no problem arguing with the interviewer
What’s the difference between String, StringBuilder, and StringBuffer
The String class is in the java.lang package. The String class is final. Once a String is created, it cannot be modified. Any modification of a String is equivalent to recreating a String. String The bottom layer of a String is implemented using StringBuilder
StringBuilder is a non-thread-safe container under the java.util package. The Append method of StringBuilder is often used to concatenate strings more efficiently than the + sign in String. StringBuilder is not generally used in concurrent environments
A StringBuffer is stored in the java.util package. StringBuffer is a thread-safe container and is commonly used as a string concatenation in multithreaded scenarios
AbstractStringBuilder and StringBuffer are both derived from the AbstractStringBuilder class, which implements the general operations of StringBuffer and StringBuilder.
See this article for an in-depth look at Strings, StringBuilder, and StringBuffer
What is dynamic proxy based on
Proxy is generally divided into static proxy and dynamic proxy, which are both applications of the proxy mode. Static proxy means that the program is compiled before it runs, and the program knows who will execute the proxy method.
Dynamic proxy can only be determined during program running. Compared with static proxy, dynamic proxy has the advantage that it is convenient to uniformly handle the functions of proxy classes without modifying the methods in each proxy class. Dynamic proxies are implemented based on reflection. Reflection allows us to manipulate classes or objects directly, such as getting the class definition, getting declared properties and methods, calling methods, and modifying the class definition at run time.
Dynamic proxy is a mechanism that builds proxies at run time and handles method calls dynamically. Dynamic proxies are implemented in many ways. Java provides proxies called JDK dynamic proxies, which are based on class inheritance.
Understand dynamic proxies refer to this article for an in-depth understanding of dynamic proxies
Several implementations of dynamic proxy
I’ll give you a list of four ways to implement dynamic proxies, respectively
- JDK dynamic proxy: A JDK dynamic proxy is also a Java dynamic proxy, which is an interface-based dynamic proxy that typically proxies all classes under an interface.
- CGLIB dynamic proxy: CGLIB dynamic proxy for class implementation proxy, mainly on the specified class to generate a subclass, overrides the methods, that is, CGLIB dynamic proxy using class inheritance -> method rewrite.
- Javassist agent:
Javassist
Is a class library for editing bytecodes in Java; It enables Java programs to define a new class at run time and modify the class file when the JVM loads. - ASM Proxy: ASM is a Java bytecode generation architecture that can dynamically generate subclasses or other proxy classes in binary format or modify classes before they are loaded into memory by the Java virtual machine.
The implementation of these four bytecodes can refer to dynamic proxies surprisingly simple!
Serialization and Deserialization
Serialization means Serialization. Objects that implement Serialization and deserialization must implement the Serializable interface. Serialization means turning objects into byte streams and storing them to disk or network. Deserialization is the reverse of serialization.
One of the questions I often ask when I learn about serialization is, why do objects need to be serialized?
For data transfer purposes, because this object is in object format in your code, but it’s not in object format in transmission, so when some other process or some other machine wants to communicate with you, you both send various types of data, and you may send this object, So the object must be converted to a format that can be recognized on the network or on disk, which is binary.
That is, the sender needs to convert the Java object into a sequence of bytes before it can be sent over the network; The receiver needs to restore the byte sequence back to Java objects, which is what the Deserialization interface does.
The difference between int and Integer
There are a lot of differences between int and Integer
- Int is the basic data type in Java, and int stands for
The integer
Int is allocated on the stack in the Java memory model. Int has no methods. - Integer is a wrapper class for basic data types in Java. Integer is an object that can make method calls. The default value of Integer is null, and Integer is allocated in the heap in the Java memory model. Int and Integer can be converted to each other during computation, and the process of int -> Integer is called
packing
, Integer -> int is calledSplit open a case
, Integer and IntegerCache will automatically cache values from -128-127
For an in-depth understanding of unpacking and unpacking, see this article for a detailed explanation of automatic packing and unpacking in Java
What I/O methods Java provides
There are many Java I/O methods. Traditional I/O is also called BIO.
Java I/O packages are relatively simple to implement, but prone to performance bottlenecks, and traditional I/O is based on synchronous blocking.
NIO, which comes with JDK 1.4, is a java.nio package that provides abstractions based on channels, selectors, and buffers to build multiplexing, synchronous, non-blocking I/O programs.
NIO was further improved after JDK 1.7 to introduce an Asynchronous non-blocking approach, also known as AIO(Asynchronous IO). We can use an example in daily life to illustrate: the project manager will not wait for the staff to solve a bug, but will assign bugs to other staff or do other things during the time when the staff solves the bug, and then tell the project manager that the bug is solved after the staff solves the bug.
Learn more about IO by referring to this article.
Talk about design patterns you know
A mind map town field
For example, global uniqueness can be used in the singleton pattern.
Excessive if… can be optimized using policy patterns. else…
Develop standards using template patterns
Take over someone else’s pot, but do not want to change the original class adapter pattern
Use composition rather than inheritance
Use a decorator to make sweetened, cheesy coffee
The agent can be used by any middleman……
Write out several singleton pattern implementations
This is one of the most common interview questions that you will not be asked to write a singleton. Even by hand, all you need to do is write key code. There are several implementations of the singleton pattern, and if there are any problems with each implementation.
The general answer is this
- Hungry: thread-safe, high call efficiency, but no delay loading
- Lazy: thread-safe, inefficient calls, but slow loading
- Double CheckLock implementation singleton: DCL is also known as Double lock determination mechanism (due to the JVM underlying model, occasionally problems, not recommended
- Static internal class implementation mode: thread-safe, high call efficiency, can be delayed loading
- Enumerated classes: thread-safe, efficient calls, no delay loading, and naturally prevent reflection and deserialization of calls
If you want to learn more about this interview question, I explained the singleton to the interviewer, and he gave me a thumbs up
What is the difference between Comparator and Comparable
-
Comparable is more like a natural sort
-
The Comparator is more like custom sorting
When co-existing, use the Comparator rule for comparison.
For common data types (e.g. String, Integer, Double…) They implement the Comparable interface by default and implement the compareTo method, which we can use directly.
For custom classes that may need to implement different comparison policies in different situations, we can create a new Comparator interface and use a specific Comparator implementation for comparison.
For an in-depth understanding of Comparable and Comparable, see this article on understanding Comparable and Comparable.
What methods are commonly found in the Object class
The Object class is the parent of all objects and contains methods that all objects can use
- HashCode () : hashCode used to evaluate an object
- Equals () : Used to compare values between objects
- ToString (): Used to convert objects to strings
- Clone (): Used for copying objects
- Wait (): Used to wait between objects
- Notify (): Used to notify an object to release resources
- NotifyAll (): Notifies all objects to release resources
- Finalize (): Used to inform garbage collector to collect garbage
- GetClass (): Used to get object classes
Java generics and type erasure
One article on Java generics and erasure is enough.
The rationale for reflection, what are the three ways that reflection creates class instances
The reflection mechanism enables Java programs to have introspect capability at runtime. Through reflection, we can directly manipulate classes and objects, such as obtaining the definition of a class, obtaining the attributes and methods of the class, and constructing methods.
There are three ways to create an instance of a class
- Object instance. GetClass ();
- Created by class.forname ()
- Object instance newInstance() method creation
For an in-depth understanding of reflection, please refer to learn to reflect after I was admitted! (dry)
Strong reference, if reference, virtual reference and phantom reference
The different reference types are logical, but for virtual machines, the reachable status of the object and its impact on the garbage collector are important.
The following flow summarizes the life cycle of an object
The object is created, initialized, used at run time, and then out of scope. The object becomes unreachable and is collected by the garbage collector. The areas indicated in red indicate that the object is in a strongly reachable phase.
JDK1.2 introduces the java.lang.ref package, which has four stages in the life cycle of objects: Strongly Reachable (Strongly Reachable), Soft Reachable (Soft Reachable), Weak Reachable port (Weak Reachable port), and Phantom Reachable port (Phantom Reachable port).
If you only talk about objects that qualify for garbage collection, there are only three: soft reachable, weak reachable, and phantom reachable.
-
Soft reachable: is a state that can be accessed only by soft referencing . A soft reachable object is an object referenced by SoftReference and has no strong reference. Soft references are used to describe objects that are useful but not necessary. The garbage collector holds soft-referenced objects as long as possible, but reclaims soft-referenced objects before an OutOfMemoryError occurs. OutOfMemoryError is thrown if there is not enough memory to allocate after the soft reference object has been reclaimed.
-
Weakly reachable: Weakly reachable objects are objects referenced by WeakReference. The garbage collector can collect weakly referenced objects at any time and does not attempt to preserve soft-referenced objects.
-
Phantom reachability: phantom reachability is the object referenced by PhantomReference. Phantom reachability is when there is no strong, soft and weak reference correlation, and the object has been finalize, and only PhantomReference points to this object.
In addition, there are two reachable and unreachable judgment conditions
- Strongly reachable: when an object is created, initialized, or in use, it is in a strongly reachable state
Inaccessible (unreachable)
: An unreachable object means that the object can be cleared.
Below is a transition diagram of different accessibility states
Determining reachable conditions is also part of how the JVM garbage collector decides to process objects.
All object reachability references are subclasses of java.lang.ref.reference, which has a get() method that returns the Reference object. This method returns NULL if the reference object has been cleared programmatically or by the garbage collector. That is, with the exception of phantom references, both soft and weak references can get objects. And these objects can be artificially saved by making strong references, such as assigning the this keyword to an object, by re-associating it with any object in the reference chain.
For an in-depth understanding of citation issues, check out this article for an in-depth understanding of various citation issues.
The difference between final, finally and Finalize ()
There is no connection between the three. As we mentioned above, final can be used to modify classes, variables and methods. Please refer to the interview question about final above.
Finally is a keyword that is often used with the try block for exception handling. Using a try… The finally part of the code must be executed, so we often use the finally method to close resources.
In JDK1.7, try-with-resources is recommended as an elegant way to close a resource. It simply closes the resource with a try(){} instead of the finally keyword.
Finalize is a method in Object, which is used to collect objects. We generally do not recommend using Finalize, which is associated with garbage collection. In Java 9, Finalize is marked as deprecated. Don’t implement finalize methods and don’t count on them to do garbage collection without a specific reason.
To have a deeper understanding of final, finally and Finalize, you can read the final, Finally and Finalize, and finalize with the interviewer.
What are the classifications of inner classes? Explain them separately
In Java, you can put the definition of one class inside the definition of another class, called an inner class. The inner class is itself an attribute of the class, as defined by other attributes.
There are generally four main classifications of inner classes
- Member inner class
- Local inner class
- Anonymous inner class
- Static inner class
A static inner class is a static class defined inside a class. A static inner class can access all static variables of the external class, but not the non-static variables of the external class.
A member inner class is a non-static class defined inside a class at a member location. Member inner classes can access all variables and methods of the external class, including static and non-static, private and public.
An inner class defined in a method is a local inner class. A local class defined in an instance method can access all variables and methods of the external class. A local class defined in a static method can access only static variables and methods of the external class.
An anonymous inner class is an inner class without a name. In addition to having no name, an anonymous inner class has the following characteristics:
- An anonymous inner class must inherit an abstract class or implement an interface
- Anonymous inner classes cannot define any static members or methods.
- When the parameter of the method needs to be used by an anonymous inner class, it must be declared final.
- An anonymous inner class cannot be abstract; it must implement all the abstract methods of the inherited class or implemented interface.
Name a few common exceptions
- NullPointerException: NullPointerException
- NoSuchMethodException: method not found
- IllegalArgumentException: Invalid argument exception
- IndexOutOfBoundException: array subscript cross-border anomalies
- IOException: An exception caused by a file not found, not opened, or an I/O operation cannot be performed
- ClassNotFoundException: The exception thrown by the file could not be found
- NumberFormatException: The UTF code data format of a character is incorrect.
- InterruptedException: An exception thrown by a thread interrupt
The difference between static and dynamic binding
A Java program has to go through three steps of compilation, compilation and running. Coding is not within the scope of our discussion, so we naturally focus on the two stages of compilation and running. Since the process of compilation and running is quite tedious, the following is my understanding to explain:
Java programs go through two major steps from source file creation to program execution:
Compile time is the process by which the compiler compiles a source file into bytecode
2. Bytecode files are interpreted and executed by the Java virtual machine
The binding
A binding is a call to a method and the process of connecting it to the class that called the method is called binding.
There are two main types of binding:
Static and dynamic binding
Other names for binding
Static binding == early binding == compile-time binding
Dynamic binding == late binding == runtime binding
For the sake of distinction: static binding and dynamic binding are collectively called below
Static binding
Before the program runs, at compile time, the JVM can determine who is calling the method, a mechanism called static binding
Identify the three keywords for static binding and their respective understandings
If a method is decorated with any of the keywords private, static, or final, the method is pre-bound
Constructors are also pre-bound
Private: The private keyword means private. If a method modified by private cannot be called by any other class, that is, a method that is unique to this class, so it is up to the compiler to identify which class the method belongs to
public class Person {
private String talk;
private String canTalk(a){
returntalk; }}class Animal{
public static void main(String[] args) {
Person p = new Person();
// The private modifier is unique to the Person class, so the Animal class cannot access it.
// p.canTalk();}}Copy the code
Final: Final modified methods cannot be overridden, but can be called by subclasses, effectively turning off dynamic binding if the method is declared final
public class Fruit {
private String fruitName;
final String eatingFruit(String name){
System.out.println("eating " + name);
returnfruitName; }}class Apple extends Fruit{
// Final methods cannot be overridden. The eatingFruit method belongs only to the Fruit class and cannot be called by the Apple class
// String eatingFruit(String name){
// super.eatingFruit(name);
/ /}
String eatingApple(String name){
return super.eatingFruit(name); }}Copy the code
Static: Static modifier methods are special. They are called by the class name instead of new. The variable name calls the method directly, and that’s the key, new is the key, or you can think of it as the trigger that starts polymorphism, and the class name. If the class name is called directly, the class name is determined and no polymorphism is generated.
public class SuperClass {
public static void sayHello(a){
System.out.println("Hello by superClass"); }}public class SubClass extends SuperClass{
public static void sayHello(a){
System.out.println("Hello by SubClass");
}
public static void main(String[] args) { SuperClass.sayHello(); SubClass.sayHello(); }}Copy the code
SubClass inherits from SuperClass
You can’t override sayHello(), which means that sayHello() is hidden from subclasses, but you can write your own sayHello(), which is SubClass sayHello(). Methods are decorated with the static keyword and are also compile-time bound
Dynamic binding
Binding is done at run time based on the type of the specific object
In addition to methods and constructors that are decorated by private, final, and static, the process by which the JVM decides at run time which object to call the method is called dynamic binding
If the compilation and execution are regarded as a timeline, the compilation process of the program must be carried out before the execution, so the binding at the compilation time is the early binding, and the binding at the execution time is the late binding.
public class Father {
void drinkMilk(a){
System.out.println("Father likes milk."); }}public class Son extends Father{
@Override
void drinkMilk(a) {
System.out.println("The son likes milk.");
}
public static void main(String[] args) {
Father son = newSon(); son.drinkMilk(); }}Copy the code
The Son class inherits the Father class and overwrites the dringMilk() method. The result is that the Son likes to drink milk. So what is the binding method above?
The above binding method is called dynamic binding, because when you write Father son = new son (), the compiler does not know who the son object actually refers to. At runtime, the compiler knows that son is a Father object, but refers to a reference to son. This concept is called polymorphism, so we can formulate the three principles of polymorphism:
-
inheritance
-
rewrite
-
A superclass reference points to a subclass object
That is, at Father son = new son (), the dynamic binding mechanism is triggered.
Dynamic binding process
- Table of methods used by virtual machines to extract the actual types of objects;
- Vm search method signature;
- Call the method.
Dynamic and static binding characteristics
Static binding
Static binding is triggered at compile time, so its main characteristics are
1, compile time trigger, can know the code error in advance
2. Improve the efficiency of program operation
Dynamic binding
The premise of using dynamic binding improves the availability and flexibility of your code.
2. Polymorphism is the basis of design patterns and can reduce coupling.
What syntax sugar is in Java
Syntactic sugar is a syntax added to a computer language that has no effect on the language’s functionality but is more convenient for programmers to use. Because Java code needs to run in the JVM, the JVM does not support syntactic sugar. Syntactic sugar is reduced to simple basic syntactic structures during compilation, which is called syntactic sugar.
Here’s a list of syntax sugar in Java
-
Generics: Generics are a syntactic sugar. In JDK1.5, generics were introduced, but the generics mechanism itself is implemented through type erase. there are no generics in the JVM, only normal types and methods, and the type parameters of a generic class are erased at compile time.
-
Autounboxing and autoboxing: Autounboxing and autoboxing are syntactic candy that refers to automatic conversions between the eight basic data types of the wrapper classes and their base data types. Simply put, boxing automatically converts the base data type to the wrapper type; Unpacking automatically converts wrapper types to primitive data types.
-
Inner class: The inner class is also a syntactic sugar because it is just a compile-time concept. Once compiled, the compiler generates a separate class file for the inner class called outer$innter.class.
-
Variable-length arguments: Variable-length arguments are also a relatively minor usage. Variable-length arguments are those that a method can accept as arguments of indeterminate length. Variable-length parameters are not generally used in our development, and they are not recommended, as they can make our programs difficult to handle.
-
Enhanced for loops: Enhanced for loops are much more powerful and much cleaner than normal for loops. You don’t need to know how many times you iterate or the index of the array. The object that enhances the for loop is either an array or implements the Iterable interface. This syntactic sugar is used to iterate over an array or collection and cannot change the size of the collection during the loop.
-
Switch supports strings and enumerations: the Switch keyword native supports only integer types. If a switch is followed by a String, the compiler converts it to the value of the String’s hashCode, so the switch syntax compares the String’s hashCode.
-
Conditional compilation: In general, all lines in the source program participate in compilation. However, it is sometimes desirable to compile a part of the content only if certain conditions are met, that is, to specify compilation conditions for a part of the content, which is conditional compile.
-
Assertions: The so-called Assert keyword is a new feature added in JDK 1.4. It is mainly used during code development and testing to determine certain critical data, and if the key data is not what your program expected, the program will warn or quit.
-
The try – with – resources: Starting with JDK 1.7, Java introduced the try-with-resources declaration, simplifying the try-catch-finally statement to a try-catch, which is a syntactic sugar that is converted to a try-catch-finally statement at compile time. The new declaration contains three parts: a try-with-resources declaration, a try block, and a catch block. It requires variables defined in the try-with-resources declaration to implement the AutoCloseable interface so that their close methods can be called automatically in the system, replacing the closing of resources in finally.
-
String addition: There are two types of string concatenation. If the concatenation result can be determined at compile time, the string concatenated using the + sign will be optimized by the compiler. If the concatenation result cannot be determined at compile time, the string will be concatenated using the AppEnd of The StringBuilder
For an in-depth understanding of Java syntax sugar, see this article about syntax sugar in Java.
List and Set
This is also a platitude question.
The same
There are three types in the Java collection: List, Set, and Map, all of which live under the java.util package and are interfaces with their own implementation classes.
List implementation classes include ArrayList, LinkedList, Vector, CopyOnWriteArrayList, etc
The implementation classes of Set include HashSet, TreeSet, LinkedHashSet, SortedSet, etc
They also have their own abstract classes, AbstractList for List and AbstractSet for Set. Abstract classes are mainly used as top-level interfaces, that is, extensions of List and Set interfaces. They implement some top-level interface functions and define some template methods, which use the template design pattern.
Lists and sets both inherit the Collection interface and belong to one kind of Collection.
Let’s talk about the differences between lists and sets
The difference between
order
List represents an ordered set, that is, the elements in the List are arranged in an orderly manner. The List interface can accurately control the insertion order of each element and search for elements through the index.
Different implementation classes can define their own order. For example, a HashSet is an unordered data structure. The elements in a HashSet are out of order. TreeSet sorts the elements in their natural order; LinkedHashSet is sorted by the order of the elements inserted into the Set; The SortedSet will sort according to the Comparable or Comparator comparison order, which means you can customize the sorting.
Whether the element repeats
A List allows duplicate elements, and a List can insert null elements, whereas a Set does not allow duplicate elements, so a Set can only allow one NULL element.
Tell me what you know about Map
Map is also a collection class that we use a lot in our daily development.
A Map is an object that supports key-value, or key-value pair storage. Where key objects are not allowed to repeat, value objects are allowed to repeat, and value objects can be of type Map, just as elements in arrays can be arrays.
The Map interface is implemented in HashMap, TreeMap, and LinkedHashMap classes.
HashMap is the most common implementation of a Map. The underlying structure of a HashMap is an array + linked list. It stores data according to the hashCode value of the key. And only one NULL key-value pair is allowed. When there are few elements in a HashMap, the HashMap stores elements in the form of a linked list. When the amount of data reaches a certain level, the linked list is converted to a red-black tree for storage.
TreeMap is a Map of a red-black tree. It sorts the keys in the specified order. TreeMap is not a thread-safe Map.
LinkedHashMap ensures that elements are inserted in order, traverses the query slower than a HashMap, and is also not thread-safe. LinkedHashMap allows empty elements.
It is worth noting that Map implementations include Hashtable and ConcurrentHashMap, both of which are thread-safe maps.
Hashtable is not commonly used because it is thread-safe and uses a simple and violent synchronized lock, which is expensive and not recommended.
ConcurrentHashMap is a multi-threaded Map with high concurrency. It is often used in multi-threaded scenarios. The underlying ConcurrentHashMap uses segmented locks, which lock each segment. Reduces lock granularity while ensuring thread safety.
The difference between ArrayList, LinkedList, and Vector
ArrayList is a data structure based on dynamic arrays, and LinkedList is a data structure based on linked lists.
ArrayList is superior to LinkedList for random access to GET and set operations because LinkedList moves the pointer.
For add and remove operations, LinedList has an advantage because ArrayList moves data.
ArrayList, and LinkedList isn’t thread safe easy, they all need manual lock, or use the Collections of the realization of thread-safe Collections. SynchronizedList to construct. They all have fail-fast.
This is probably the time to ask you andVector
The difference between
There are two main differences: thread safety and capacity expansion
Vector, like ArrayList, is implemented using arrays. The difference is that it supports thread synchronization, which means that only one thread can write a Vector at a time. This avoids the inconsistencies caused by multiple threads writing simultaneously, but synchronization is expensive and therefore slower to access than ArrayList.
When an element in a Vector or ArrayList exceeds its initial size, Vector doubles its capacity, while ArrayList increases its size by only 50%. In this way, ArrayList helps save memory space.
The implementation principles of collections. sort and arrays. sort
Here’s the source code for collections.sort and arrays.sort
From the three sections of the code, the Collections. Sort the final call is Arrays. The sort of method, so the Collections. Sort need not see, see Arrays directly. Sort.
The arrays.sort source code has three branch judges. If no external Comparator is provided, the sort method is called directly
First will be LegacyMergeSort userRequested judgment, the judgment is what mean?
In JDK1.6, LegacyMergeSort is used. In JDK1.7, TimeSort is used. If you want to use the original LegacyMergeSort, you need to add it to the system variable
-Djava.util.Arrays.useLegacyMergeSort=true
Copy the code
This configuration.
If this configuration is not used, the default is to call the comparableTimsor.sort method, which is an optimization of TimSort, whose sorting algorithm is merge sort.
We also see this in the second judgment from arrays.sort. The biggest difference between a ComparableTimSort and a TimSort is that you provide an external comparator.
What is the difference between Iterator and ListIterator
ListIterator is an Iterator that we use a lot in our daily development. ListIterator is a ListIterator that we use a lot in our daily development. ListIterator is a ListIterator that we use a lot in our daily development.
In general, the main differences between Iterator and ListIterator are
-
Iterator must not modify the number of elements in the collection during iterating. Otherwise, an exception will be thrown.
-
Iterator can be used in all collections, while ListIterator can only be used in List types and subtypes
-
ListIterator has the add method, which adds elements to a collection, whereas Iterator does not.
-
Listiterator and Iterator both have hasNext and next methods that traverse elements sequentially, but Listiterator has hasprevious and previous methods that traverse elements backwards
-
NextIndex and previousIndex do this. Iterator does not
-
Listiterator allows you to modify objects. Set () allows you to do this. Iterator can only iterate over objects, not modify them.
Talk about the expansion mechanism for ArrayList
Today the interviewer asked you again about the expansion mechanism of ArrayList… Just look at the source code
When will the expansion happen? When will the add method be called
ArrayList adds elements to do that, and that’s what the ensureCapacityInternal method does, which is a way of determining and determining the capacity, so we’ll just go in there
And what this method does is it makes a judgment, as you can see in the comment above, about whether or not your ArrayList was constructed with an initial capacity, and if there are no elements in the List, it takes the judgment between the initial capacity and the maximum capacity in the ArrayList, whichever is larger.
Then call the ensureExplicitCapacity method to determine whether expansion is required
As you can see, if the size of the elements in the ArrayList is larger than the size of the stored elements, the grow method is called, which is essentially an expansion method.
This code is the ArrayList expansion mechanism. So let’s analyze it
First, the number of elements in the ArrayList is obtained, and then the capacity of the ArrayList is expanded by 50%. The expanded capacity is compared with the parameter capacity. If it is smaller than the parameter capacity, the value of a larger capacity is used to copy elements. If the capacity is larger than the maximum capacity of the ArrayList, the maximum capacity is evaluated
The hugeCapacity method first determines whether the parameter is less than zero. If so, it raises an OutOfMemoryError. If not, it determines whether the parameter or the ArrayList has the largest capacity. The value is integer. MAX_VALUE, or MAX_ARRAY_SIZE if it’s small.
BIO, NIO, AIO
To put it simply, BIO(Blocking I/O) is a synchronous Blocking I/O. Data is read and written in a single thread. That is, it has only one sequential stream.
NIO(non-blocking IO) is also called new IO. It is a synchronous non-blocking IO model added to JDK 1.4 and later. In NIO, threads make requests and return immediately. Synchronization means they have to wait for the IO buffer to be ready, not blocking. Instead of waiting for the IO buffer to be ready, the user thread can do something else first, but polling periodically to check whether the IO buffer is ready. NIO in Java stands for New IO. NIO plus IO multiplexing. Whereas normal NIO is threads polling to see if an IO buffer is ready, new IO in Java is threads polling to see which IO buffers are ready, an idea of I/O multiplexing. In the IO multiplexing model, the task of checking the I/O data readiness is assigned to the system-level SELECT or Epoll model, which is monitored by the system to reduce the burden of user threads.
AIO is truly an asynchronous non-blocking IO model. In the NIO implementation above, the user thread is required to poll periodically to check whether the IO buffer data is ready, occupying the thread resources of the application. In fact, polling is still blocking, not really freeing the current thread, because it still needs to query which IO is ready. The real ideal of asynchronous non-blocking IO would be to let the kernel do it, and the user thread would simply tell the kernel to either notify me when the buffer is ready or execute the callback I’ve given you.
Deep copy is different from shallow copy
In Java, there are two types of object properties, based on how much they are copied (base data class and reference type) :
- Shallow copy
Shallow Copy
- Deep copy
Deep Copy
Shallow copy: A shallow copy recreates an object with a copy of the original object property values. If the property is of a primitive type, the value of the primitive type is copied. If the property is a memory address (reference type), the memory address is copied, so if one object changes the address, the other object will be affected. That is, the default copy constructor only copies objects shallowly, member by member, that is, only the object space is copied, not the resource.
To implement shallow copy, implement the Cloneable interface and override the clone() method.
Deep copy: For member objects of primitive data types, the attribute value is directly assigned to the new object because the primitive data type is value passed. A basic type of copy in which one object changes the value without affecting the other (as in a shallow copy). For reference types, such as arrays or class objects, deep copy creates a new object space and copies its contents, so they point to different memory Spaces. Changing one does not affect the other. For multiple layers of objects, Cloneable override clone() is required for each object, thus realizing serial layer copies of objects. Deep copy is slower and more expensive than shallow copy.
Java creates objects in five ways
Java creates objects in five main ways
- Use new to create objects
Object obj = new Object();
Copy the code
- Use the newInstance method to create
User user = (User)Class.forName("com.cxuan.test.User").newInstance();
// or use
User user = User.class.newInstance();
Copy the code
- Use reflection to create objects
Constructor<User> constructor = User.class.getConstructor();
User user = constructor.newInstance();
Copy the code
- Use object cloning to create objects
Constructor<User> constructor = User.class.getConstructor();
User user = constructor.newInstance();
user.setName("cxuan");
User user2 = (User)user.clone();
System.out.println(user2.getName());
Copy the code
- Create objects using deserialization
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxx"));
out.writeObject(user2);
out.close();
//Deserialization
ObjectInputStream in = new ObjectInputStream(new FileInputStream("xxx"));
User user3 = (User) in.readObject();
in.close();
user3.setName("cxuan003");
System.out.println(user3 + ", hashcode : " + user3.hashCode());
Copy the code
For a better understanding of how to create objects, see the n operations for creating objects in Java
trivia
This article took a long time to write. The statistics of wechat official account is 3W words, 31 pictures, and the reading time is about 77 minutes.
I know that this reading time can take the subway line 10 around Beijing, there will be a lot of people will be disgusted, the article is so long, who has time to finish it? I’ve heard this fast-food question a million times, and it just falls on deaf ears. Yes, we every day, brush douyin to see beautiful women, brush the headlines to see beautiful women, brush the public account to see a group of bigwigs bragging every day, and then scold: “God, waste me another hour”, and then pretend to seriously look at the code for 15 minutes, continue to waste.
I know this article is still not read by many people, because it will soon be inundated by the flood of information. Maybe you will put it in your favorites after reading it. Even if you think it is a child’s child, this article may not be a ripple in your programming career. Let me just say what I did. There are probably less than 20 links in this article, 14 of which are from my official account.
StringBuffer, StringBuilder, StringBuffer
Can a little static still daunch me?
By the end of this HashMap, you’ll be fine with bickering with your interviewer
After reading the Exception and Error, you will have no problem arguing with the interviewer
In-depth understanding of dynamic proxies
Dynamic proxies are surprisingly simple!
In-depth understanding of IO
I explained the singleton model to the interviewer and he gave me a thumbs up
Comparable and Comparator
After learning reflexes, I was accepted! (dry)
In-depth understanding of various reference issues
After reading the final, Finally and Finalize, you will have no problem arguing with the interviewer
Syntax sugar in Java, so sweet.
Enumerates the n operations that Java uses to create objects
I think, this can be right up my github github.com/crisxuan/be… The words above.
Ok, that’s it, as for what the “like” is looking at, feel free, I hope this article can help you.
I have uploaded six PDFS by myself. After searching the public account of “Programmer Cxuan” on wechat, I reply to CXuan on the background and get all PDFS. These PDFS are as follows
Six PDF links