At the end of 2013, I saw an article called “Java Interview Questions” circulating on the Internet. After careful reading, I found that many of the questions in it were repetitive and worthless, and many reference answers were also wrong. So I spent half a month revising and republishing the so-called “Java Interview Complete book” on my CSDN blog. In the process of revision, according to the latest VERSION of JDK at that time (Java 7), the answer to the question and relevant codes were given, and useless or outdated contents such as EJB 2.x and JSF were removed. Data structure and algorithm, large website technical architecture, design pattern, UML, Spring MVC and other contents are supplemented, and many knowledge points are deeply analyzed, such as the design of hashCode method, garbage collection, concurrent programming, database transactions and so on. I even wanted to include operating system, database, software testing, etc., which often come up in interviews, but for various reasons, I only managed to compile 150 interview questions. To my delight, these 150 questions have helped a lot of people, and have been viewed more than 50,000 times on my CSDN blog, and eventually reposted by many websites and individuals in original ways. In the last year, when I searched “Java interview “on Baidu, all the things I wrote were in the top 5 of the search results, which made me think” Alexander “, because if my writing is inaccurate, it may mislead many people. In 2014, I sorted out another 30 questions, hoping to make up the interview questions and knowledge points that I had missed before, but I still felt that they were missing everything, and many new things needed to be summarized and sorted out after the release of Java 8. For this reason, I modified the previous question 180 more than once until I felt a little tired or bored. Since 2014, many of my students have been working as Java programmers and Java engineers, and their interview experience has not yet been shared with everyone. Somehow, there seems to be a force to stimulate me to write a new “Complete Set of Java Interview Questions”, so this article was born. Please don’t blame me for rewriting the same content, because every time I write something repetitive, I need to rethink the programming language and related technology, not only carefully but also to perfect it, so trust me to share something new, better, and more beneficial. These contents also speak to the thoughts, spirits and emotions of a professional programmer and trainer.

1. What are the features of object-oriented? A: Object-oriented features mainly have the following aspects: – abstraction: abstraction is the process of summarizing the common characteristics of a class of objects to construct a class, including data abstraction and behavior abstraction. Abstractions focus only on what properties and behaviors an object has, not on the details of those behaviors. – Inheritance: Inheritance is the process of creating a new class by obtaining inheritance information from an existing class. Classes that provide inheritance information are called superclasses (superclasses, base classes); The class that gets the inheritance information is called a subclass (derived class). Inheritance gives some continuity to a changing software system, and is also an important means of encapsulating variable factors in the program (please read Dr. Yan Hong’s “Java and Patterns” or the section on bridge patterns in “Design Patterns Refinement” if you don’t understand). – Encapsulation: Encapsulation is generally considered to bind data to methods that manipulate data. Data can only be accessed through defined interfaces. The essence of object orientation is to represent the real world as a series of completely autonomous, closed objects. The methods we write in our classes encapsulate the implementation details; We write a class that encapsulates data and data operations. It can be said that encapsulation is to hide everything that can be hidden, providing only the simplest programming interface to the outside world (think of the difference between ordinary washing machine and automatic washing machine, automatic washing machine is obviously better packaging and therefore easier to operate; The smartphones we use today are packaged well enough to do everything with a few buttons.) – Polymorphism: Polymorphism allows objects of different subtypes to respond differently to the same message. Simply put, the same object reference calls the same method but does different things. Polymorphism is divided into compile-time polymorphism and run-time polymorphism. If an object’s methods are viewed as services that the object provides to the outside world, then runtime polymorphism can be interpreted as: When the service system to provide A system access B, B system has A variety of way of the services they offer, but everything is transparent for A system (like electric razor is A system, its power supply system is B, B system can use the batteries or use alternating current (ac), and even may be solar energy, A system will only by the method of class B object call power supply, But it is not known what the underlying implementation of the power supply system is or how it is powered). Method overload implements compile-time polymorphism (also known as pre-binding), while method override implements runtime polymorphism (also known as post-binding). Runtime polymorphism is the essence of object orientation. To implement polymorphism, you need to do two things: 1). Method rewriting (when a subclass inherits a parent class and overwrites an existing or abstract method in the parent class); 2). Object modeling (using a parent type reference to refer to a subtype object, so that the same reference calls the same method and behaves differently depending on the subtype object).

2, access modifiers, public, private, protected, and don’t write what is the difference between (the default)? A:

The modifier The current class With the package The child class Other packages
public Square root Square root Square root Square root
protected Square root Square root Square root x
default Square root Square root x x
private Square root x x x

Class members default to default when they do not write access modifiers. The default is public for other classes in the same package and private for classes not in the same package. Protected is public for subclasses and private for classes that are not parent-child in the same package. In Java, external class modifiers can only be public or default, and class members (including inner classes) can have the above four modifiers.

Is String the most basic data type? Answer: No. There are only eight basic data types in Java: byte, short, int, long, float, double, char, Boolean. Except for primitive type and enumeration type, all the other types are reference types.

4, float f = 3.4; Is that correct? Answer: Not true. 3.4 is a double. Assigning a double to a float is down casting and will result in a loss of precision. Therefore, a cast float f =(float)3.4 is required. Or float f = 3.4f; .

5, short s1 = 1; s1 = s1 + 1; Didn’t you? short s1 = 1; s1 += 1; Didn’t you? Answer: for short s1 = 1; s1 = s1 + 1; Since 1 is an int, s1+1 is also an int and requires a cast to assign to short. Short s1 = 1; s1 += 1; It compiles correctly because s1+= 1; S1 = (short)(s1 + 1); There is an implicit cast.

Does Java have a Goto? A: Goto is a reserved word in Java and is not used in the current version of Java. The appendix to The book “The Java Programming Language” by James Gosling gives a list of Java keywords, including goto and const, but these are not currently available. Therefore, some places call it reserved word, but the term reserved word should have a broader meaning, because programmers familiar with C know that words or combinations of words that have special meaning are regarded as reserved words.)

What is the difference between an int and an Integer? A: Java is an almost pure object-oriented programming language, but it still introduces basic data types for programming convenience, but in order to treat these basic data types as objects, Java introduces a corresponding Wrapper class for each basic data type. The wrapper class for int is Integer, and since Java 5 automatic boxing/unboxing has been introduced to make them interchangeable. Java provides a wrapper type for each primitive type: Boolean, char, byte, short, int, long, float, double – Wrapper type: Boolean, Character, byte, short, Integer, long, float, double

class AutoUnboxingTest { public static void main(String[] args) { Integer a = new Integer(3); Integer b = 3; int c = 3; System.out.println(a == b); System.out.println(a == c); }}Copy the code

Recently, I encountered an interview question, which is also related to automatic packing and unpacking. The code is as follows:

public class Test03 { public static void main(String[] args) { Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System.out.println(f1 == f2); System.out.println(f3 == f4); }}Copy the code

It’s easy to assume that both outputs are either true or false if you don’t know what you’re doing. The first thing to note is that the variables f1, f2, f3, and F4 are all Integer object references, so the == operation below compares references rather than values. What is the nature of packing? When we assign an int value to an Integer object, valueOf, the static method of the Integer class, is called. If you look at valueOf’s source code, you can see what happens.

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }Copy the code

IntegerCache is the inner class of Integer, and its code looks like this:

/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the {@code -XX:AutoBoxCacheMax=} option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { 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); h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); assert IntegerCache.high >= 127; } private IntegerCache() {} }Copy the code

To put it simply, if the Integer literal is between -128 and 127, then no new Integer object is created, but the Integer object in the constant pool is referenced directly, so f1==f2 is true and F3 ==f4 is false.

Note: the more seemingly simple the interview questions, the more mystery, the need for the interviewer to have considerable skills.

8. The difference between & and &&? Answer: The & operator can be used in two ways: (1) bitwise and; (2) Logic and. The && operator is the short-circuit and operation. The difference between logic and short-circuit and is huge, although both require booleans on the left and right sides of the operator to be true for the entire expression. Am& is called short-circuited because if the expression to the left of am& is false, the expression to the right will be short-circuited and not evaluated. In many cases, you might want to use ampersand instead of ampersand. For example, when verifying that the user’s login name is not null and not an empty string, you should write: username! = null &&! If the first condition is not true, then a NullPointerException will be generated. If the first condition is not true, then a NullPointerException will be generated. Note: the Boolean or operator (|) and short circuit or operator (| |) difference, too.

Note: If you are familiar with JavaScript, you will probably feel the power of short-circuiting. If you want to become a JavaScript expert, start with short-circuiting.

9, Explain the use of stack, heap and static area in memory. A: Usually we define a variable of a basic data type, a reference to an object, and the field storage of function calls all use the stack space in memory; Objects created by the new keyword and constructor are placed in the heap space; Literals in the program such as the directly written 100, “hello”, and constants are placed in the static section. Stack space is the fastest to operate but the stack is small. Usually a large number of objects are placed in the heap space. In theory, the entire memory that is not used by other processes or even virtual memory on the hard disk can be used as heap space.

String str = new String("hello");Copy the code

In the above statement, the variable STR is placed on the stack, the string object created with new is placed on the heap, and the literal “hello” is placed in the static section.

Bonus: Newer versions of Java (starting with an update to Java 6) use a technique called “escape analysis” to put local objects on the stack to improve their performance.

10. How much is math.round (11.5)? What is math.round (-11.5)? Answer: Math.round(11.5) returns 12 and math.round (-11.5) returns -11. Rounding works by adding 0.5 to a parameter and rounding it down.

Can switch work on byte, can switch work on long, can switch work on String? Answer: Prior to Java 5, in Switch (EXPR), expr could only be byte, short, char, int. Since Java 5, enumeration types have been introduced in Java. Expr can also be enum types. Since Java 7, expr can also be strings, but long integers are not allowed in all current versions.

12. Calculate 2 times 8 in the most efficient way possible. Answer: 2 << 3 (moving three places to the left is the same as multiplying by two to the third, moving three places to the right is the same as dividing by two to the third).

Add: when we rewrite the hashCode method for our class, we might see something like this. We don’t really understand why we use this multiplication to produce a hashCode, why this number is prime, and why the number 31 is usually chosen. You can do your own research on the answers to the first two questions, but choose 31 because you can use shifts and subtraction instead of multiplication for better performance. By now you might have guessed that 31 * num is the same thing as (num << 5) -num. Moving 5 bits to the left is the same thing as multiplying by 2 to the fifth and subtracting itself is the same thing as multiplying by 31.

public class PhoneNumber { private int areaCode; private String prefix; private String lineNumber; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + areaCode; result = prime * result + ((lineNumber == null) ? 0 : lineNumber.hashCode()); result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() ! = obj.getClass()) return false; PhoneNumber other = (PhoneNumber) obj; if (areaCode ! = other.areaCode) return false; if (lineNumber == null) { if (other.lineNumber ! = null) return false; } else if (! lineNumber.equals(other.lineNumber)) return false; if (prefix == null) { if (other.prefix ! = null) return false; } else if (! prefix.equals(other.prefix)) return false; return true; }}Copy the code

Does array have a length() method? Does String have a length() method? A: Arrays do not have a length() method, they have a length attribute. String has the length() method. In JavaScript, the length of a string is obtained through the length attribute, which is easily confused with Java.

14. How do I get out of the current multiple nested loops in Java? A: Before the outermost loop, add A marker such as A, then use break A; You can jump out of multiple loops. (Java supports labeled break and continue statements, which act somewhat like GOto statements in C and C++, but just as goto is to be avoided, labeled break and continue statements should be avoided because they don’t make your program any more elegant, and in many cases have the opposite effect. So it’s actually better not to know.)

15. Can the constructor be overridden? A: Constructors cannot be inherited and therefore cannot be overridden, but they can be overridden.

16. Two objects with the same value (x.equals(y) == true) can have different hash codes. A: No, if two objects x and y satisfy x.equals(y) == true, they should have the same hash code. Java rules for the eqauls and hashCode methods :(1) if two objects are the same (the equals method returns true), their hashCode values must be the same; (2) If two objects have the same hashCode, they are not necessarily the same. And, of course, you may not want to do in accordance with the requirements, but if you are in violation of the principle of the above will have found in the use of the container, the same object can appear in the Set in the collection, and increase the efficiency of the new element will be dramatically reduced (for using hash storage system, if the hash code frequently conflict will cause the access performance fell sharply).

Supplement: Many Java programs know about equals and hashCode methods, but many people just know about them. In Joshua Bloch’s book Effective Java, Java Programming Minds, and Refactoring: Improving The Quality of Existing Code is a must-read for Java programmers, so if you haven’t already, buy it from Amazon), and describes equals as follows: The equals method must be reflexive (x.equials (x) must return true), symmetric (x.equials (y) must return true, and transitive (x.equials (y) and y.equials (z) must both return true). X.equials (z) must also return true) and consistency (multiple calls to x.equials (y) should return the same value when the object information referenced by x and y has not been modified), and x.equials (null) must return false for any reference to x that is not null. Tips for implementing high-quality equals methods include: 1. Use the == operator to check whether arguments are references to this object; 2. Use the instanceof operator to check whether the parameter is of the correct type. 3. For key attributes in the class, check whether the attributes of the object passed in the parameter match them; 4. After writing the equals method, ask yourself if it satisfies symmetry, transitivity, and consistency; Always rewrite hashCode when overriding equals; 6. Do not replace the Object in the equals method argument with another type, and do not forget the @override annotation when overriding.

17. Can I inherit the String class? A: The String class is final and cannot be inherited.

Add: Inheriting strings Is inherently A mistake, and the best way to reuse strings Is through association (HAS-a) and dependency (use-a) rather than inheritance (IS-A).

18. When an object is passed as a parameter to a method that changes the object’s properties and returns the changed result, is it value passing or reference passing? Answer: Value passing. Method calls in the Java language only support value passing of parameters. When an object instance is passed to a method as a parameter, the parameter’s value is a reference to that object. Properties of objects can be changed during invocation, but changes to object references do not affect the caller. C++ and C# can change the value of an argument passed in by passing a reference or passing out a parameter. It is possible to write code like this in C#, but not in Java.

using System; namespace CS01 { class Program { public static void swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } public static void Main (string[] args) { int a = 5, b = 10; swap (ref a, ref b); Console.WriteLine ("a = {0}, b = {1}", a, b); }}}Copy the code

Description: The inconvenience of not passing references in Java has not been improved in Java 8, which is why there are so many Wrapper classes in code written in Java (putting references that need to be modified through method calls into a Wrapper class and passing the Wrapper object into the method). This only leads to bloated code, especially for developers who have made the transition from C and C++ to Java programmers.

19. What is the difference between String and StringBuilder? A: the Java platform provides two types of String: a String and StringBuffer/StringBuilder, they can store and manipulate strings. String is read-only, which means that the contents of the String referenced by String cannot be changed. The StringBuffer/StringBuilder class says string objects can be modified directly. StringBuilder, introduced in Java 5, is exactly the same method as StringBuffer, except that it is used in a single-threaded environment and is more efficient than StringBuffer because none of its aspects are modified by synchronized.

Interview question 1 – what circumstances use + operator for string concatenation than call StringBuffer object/StringBuilder methods append the connection string better performance?

Interview question 2 – State the output of the following program.

class StringEqualTest { public static void main(String[] args) { String s1 = "Programming"; String s2 = new String("Programming"); String s3 = "Program" + "ming"; System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s1 == s1.intern()); }}Copy the code

Supplement: The String’s intern method gets a reference to the corresponding version of the String in the constant pool (if there is a String in the constant pool equals to true). If there is no corresponding String in the constant pool, the String will be added to the constant pool. It then returns a reference to the string in the constant pool.

20. The difference between Overload and Override. Can overloaded methods be differentiated by return type? Answer: Method overloading and overwriting are both ways of implementing polymorphism, the difference being that the former implements compile-time polymorphism, while the latter implements runtime polymorphism. Overloading occurs when a method with the same name has different argument lists (different parameter types, different number of arguments, or both) and is considered overloaded. Rewriting occurs between a subclass and its parent class. Rewriting requires that the subclass overridden method has the same return type as the parent overridden method, is more accessible than the parent overridden method, and cannot declare more exceptions than the parent overridden method (Richter’s substitution principle). Overloading has no special requirements for return types.

Question: “Why can’t overload be distinguished by return type?”

21, Describe how the JVM loads class files. A: The loading of classes in the JVM is done by the ClassLoader and its subclasses. The ClassLoader in Java is an important component of the Java runtime system that finds and loads classes in class files at run time. Because of Java’s cross-platform nature, a compiled Java source program is not an executable program, but one or more class files. When a Java program needs to use a class, the JVM ensures that the class has been loaded, wired (validated, prepared, and parsed), and initialized. Loading a class refers to reading the data from the class’s.class file into memory, usually by creating a byte array that reads into the.class file and generates a class object corresponding to the loaded class. After loading, the Class object is not complete, so the Class is not available at this point. When the class is loaded, it enters the connect phase, which consists of three steps: validation, preparation (allocating memory for static variables and setting default initial values), and parsing (replacing symbolic references with direct references). Finally, the JVM initializes the class, including: 1) if the class has a direct parent that has not already been initialized, then initialize the parent first; 2) If there are initializers in the class, execute those initializers in turn. The loading of classes is done by class loaders, including the root loader (BootStrap), Extension loader (Extension), System loader (System), and user-defined ClassLoader (a subclass of java.lang.classloader). Since Java 2 (JDK 1.2), the class loading process has adopted the parent delegate mechanism (PDM). PDM ensures the security of the Java platform. In this mechanism, the Bootstrap of the JVM is the root loader, while all other loaders have one or only one parent class loader. The loading of a class is first requested by the parent class loader, and only when the parent class loader is unable to do so is the subclass loader loaded by itself. The JVM does not provide a reference to Bootstrap to a Java program. Here are a few notes about class loaders:

  • Bootstrap: Generally implemented in native code, responsible for loading the JVM base core libraries (rt.jar).
  • Extension: Load the class library from the directory specified by the java.ext.dirs system property. Its parent loader is Bootstrap.
  • System: also called application class loader, its parent is Extension. It is the most widely used class loader. It records classes from the directory specified by the environment variable CLASspath or the system property java.class.path and is the default parent of a user-defined loader.

22. Can a char variable store a Chinese character? Why? A: The char type can store a Chinese character, because the encoding used in Java is Unicode (which is the only way to be uniform). A CHAR type is 2 bytes (16 bits), so it is ok to put a Chinese character.

Note: Using Unicode means that characters have different representations inside and outside the JVM, both inside and outside the JVM as Unicode, and encoding conversions are required when the character is transferred from inside the JVM to outside (such as into a file system). So there are byte streams and character streams in Java, and conversion streams that convert between character streams and character streams, such as InputStreamReader and OutputStreamReader, which are the adapter classes between byte streams and character streams that do the encoding conversion; For C programmers, such coding transformations may depend on the union shared memory feature.

23. What are the similarities and differences between abstract classes and interfaces? A: Neither abstract classes nor interfaces can be instantiated, but references to abstract classes and interface types can be defined. A class that inherits an abstract class or implements an interface must implement all of its abstract methods. Otherwise, the class still needs to be declared as abstract. An interface is more abstract than an abstract class, because an abstract class can define constructors, can have abstract methods and concrete methods, whereas an interface cannot define constructors and its methods are all abstract methods. Members in an abstract class can be private, default, protected, or public, while members in an interface are all public. Member variables can be defined in an abstract class, whereas member variables defined in an interface are actually constants. Classes with abstract methods must be declared as abstract classes, and abstract classes need not have abstract methods.

The difference between a Static Nested Class and an Inner Class? A: Static Nested classes are internal classes that are declared Static and can be instantiated independent of external Class instances. The normal inner class needs to be instantiated by the outer class, and the syntax looks weird, as shown below.

/** * public class {private static String[] suites = {" Spades ", "red "," flower ", "square "}; private static int[] faces = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; private Card[] cards; Public Poker() {cards = new Card[52]; for(int i = 0; i < suites.length; i++) { for(int j = 0; j < faces.length; j++) { cards[i * 13 + j] = new Card(suites[i], faces[j]); ** / public void shuffle() {for(int I = 0, len = card.length; i < len; i++) { int index = (int) (Math.random() * len); Card temp = cards[index]; cards[index] = cards[i]; cards[i] = temp; }} /** * public Card deal(int index) {return cards[index]; } /** * public class Card {private String suite; private int face; public Card(String suite, int face) { this.suite = suite; this.face = face; } @Override public String toString() { String faceStr = ""; switch(face) { case 1: faceStr = "A"; break; case 11: faceStr = "J"; break; case 12: faceStr = "Q"; break; case 13: faceStr = "K"; break; default: faceStr = String.valueOf(face); } return suite + faceStr; }}}Copy the code

Test code:

class PokerTest { public static void main(String[] args) { Poker poker = new Poker(); poker.shuffle(); Poker.Card c1 = poker.deal(0); Poker.Card c2 = Poker. New Card(" heart ", 1); System.out.println(c1); System.out.println(c2); }}Copy the code

Interview question – Where in the following code do compilation errors occur?

class Outer { class Inner {} public static void foo() { new Inner(); } public void bar() { new Inner(); } public static void main(String[] args) { new Inner(); }}Copy the code

Note: Java china-africa static inner class object creation relies on the outer class object, the interview questions above foo and the main methods are static methods that no this in a static method, that is to say there is no external class object, thus unable to create the inner class object, if you want to create the inner class object in the static method, you can do it:

    new Outer().new Inner();Copy the code

Is there a memory leak in Java? Please describe it briefly. A: Java is theoretically free of memory leaks because of its garbage collection (GC) mechanism (which is one of the reasons Java is so widely used for server-side programming); However, in real development, there may be useless but reachable objects that cannot be collected by GC, and thus memory leaks can occur. For example, Hibernate Session (level 1 cache) objects are persistent and will not be collected by the garbage collector. However, these objects may contain garbage objects that may leak memory if they are not closed or flushed. The code in the following example also causes memory leaks.

import java.util.Arrays; import java.util.EmptyStackException; public class MyStack { private T[] elements; private int size = 0; private static final int INIT_CAPACITY = 16; public MyStack() { elements = (T[]) new Object[INIT_CAPACITY]; } public void push(T elem) { ensureCapacity(); elements[size++] = elem; } public T pop() { if(size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity() { if(elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); }}}Copy the code

The code above implements a stack (FILO) structure that doesn’t seem to have any obvious problems at first glance, and it can even pass the various unit tests you write. The pop method, however, has a memory leak problem. When we pop an object from the stack, the object is not garbage collected, even if the application that uses the stack no longer references the object, because the stack maintains out-of-date references to the object. In languages that support garbage collection, memory leaks are hidden and are essentially unconscious object retention. If an object reference is inadvertently retained, the garbage collector does not process that object or any other object referenced by that object. Even if there are only a few objects, this can result in many objects being excluded from the garbage collection, which can have a significant impact on performance. In extreme cases, Disk Paging (exchanging data between physical memory and virtual memory of hard disks) can be triggered, or even cause outofMemoryErrors.

26. Can an abstract method be static, native, and synchronized? A: Neither. Abstract methods need to be subclassed, while static methods cannot be overridden, so the two are contradictory. Local methods are methods implemented by native code (such as C code), whereas abstract methods are unimplemented and contradictory. Synchronized is concerned with the implementation details of a method; abstract methods are not concerned with implementation details and are therefore contradictory.

27. Explain the difference between static variables and instance variables. A static variable is a variable that is modified by a static modifier, also known as a class variable. It belongs to a class and does not belong to any object of the class. No matter how many objects a class creates, a static variable has only one copy in memory. Instance variables must be dependent on an instance, and the object must be created and then accessed through the object. Static variables allow multiple objects to share memory.

Sidebar: In Java development, context classes and utility classes typically have a large number of static members.

28. Can calls to non-static methods be made from inside a static method? A: No, static methods can only access static members, because a call to a non-static method creates the object first, and the object may not be initialized when a static method is called.

29, how to implement object cloning? A: There are two ways: 1). Implement Cloneable and override the Clone () method in Object; 2). Implement Serializable interface, clone through object serialization and deserialization, you can realize the real deep clone, the code is as follows.

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class MyUtil { private MyUtil() { throw new AssertionError(); } public static T clone(T obj) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bout); oos.writeObject(obj); ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bin); return (T) ois.readObject(); }}Copy the code

Here is the test code:

import java.io.Serializable; /** ** @author ** / Class Person implements Serializable {private static final Long serialVersionUID = -9102017020286042305L; private String name; private int age; private Car car; public Person(String name, int age, Car car) { this.name = name; this.age = age; this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; }}Copy the code
/** ** @author ** / Class Car implements Serializable {private static final Long serialVersionUID = -5713945027627603702L; private String brand; private int maxSpeed; public Car(String brand, int maxSpeed) { this.brand = brand; this.maxSpeed = maxSpeed; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } @Override public String toString() { return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]"; }}Copy the code
class CloneTest { public static void main(String[] args) { try { Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300)); Person p2 = MyUtil.clone(p1); p2.getCar().setBrand("BYD"); System.out.println(p1); } catch (Exception e) { e.printStackTrace(); }}}Copy the code

Note: based on the realization of serialization and deserialization cloning is not only a deep, more important is through the generic limit, you can check out whether the Object supports serialization to clone, the inspection is done by the compiler, not throw an exception at run time, this is the solution using the Object class is obviously better than the method of clone cloned objects. It is always better to expose problems at compile time than to leave them at run time.

What is GC? Why GC? A: GC means garbage collection, and memory processing is the place where programmers are prone to problems. Forgetting or wrong memory collection will lead to instability or even crash of the program or system. The GC function provided by Java can automatically monitor whether the object is out of scope so as to achieve the purpose of automatic memory collection. The Java language does not provide a display operation to free allocated memory. Java programmers don’t have to worry about memory management because the garbage collector manages it automatically. To request garbage collection, one of the following methods can be called: System.gc() or Runtime.geTruntime ().gc(), but the JVM can mask the garbage collection calls displayed. Garbage collection can effectively prevent memory leaks and efficiently use available memory. The garbage collector is typically run as a single, low-priority thread that unpredictably cleans and reclaims dead or unused objects in the heap. Programmers cannot call the garbage collector in real time to collect an object or all objects. In the early days of Java, garbage collection was one of the biggest highlights of Java, because server-side programming was required to effectively prevent memory leaks. However, time has changed, and Java’s garbage collection mechanism has become a thing of the past. Mobile intelligent terminal users generally feel that iOS system has a better user experience than Android system. One of the deep reasons lies in the unpredictability of garbage collection in Android system.

Add-on: There are many garbage collection mechanisms, including generation copy garbage collection, tag garbage collection, incremental garbage collection, and so on. Standard Java processes have both stacks and heaps. The stack holds primitive local variables and the heap holds objects to be created. The Java platform’s basic algorithm for collecting and reusing heap memory is called mark and sweep, but Java improves on this with “generational garbage collection.” This method divides the heap memory into different regions according to the life cycle of Java objects. During garbage collection, objects may be moved to different regions: – Eden: This is the region where objects were originally born and, for most objects, this is the only region they have ever existed. – Survivor Paradise: Survivors from The Garden of Eden are moved here. – Tenured: This is the fate of surviving subjects old enough to survive. The minor-GC process does not touch this area. A full collection (maj-GC) is triggered when the younger generation can’t fit objects into a lifetime retirement park, which may also involve compression to make room for large objects.

JVM parameters related to garbage collection:

  • -xms / -xmx – Initial size of the heap/maximum size of the heap
  • -Xmn – Size of the young generation in the heap
  • -xx: -disableexplicitGC — disable system.gc ()
  • -xx :+PrintGCDetails — Prints the GC details
  • -xx :+PrintGCDateStamps — Prints the timestamp of the GC operation
  • -xx :NewSize/XX:MaxNewSize – Sets the new generation size/maximum new generation size
  • -xx :NewRatio – Sets the ratio of old generation to new generation
  • – XX: PrintTenuringDistribution – set output after each new generation GC survivors paradise of objects in the age distribution
  • – XX: InitialTenuringThreshold / – XX: MaxTenuringThreshold: set up the old s initial value and the maximum threshold
  • -xx :TargetSurvivorRatio: sets the target usage rate of the surviving zone

31, String s = new String(“xyz”); How many string objects are created? A: Two objects, “XYZ” for the static section and an object created on the heap with new.

32. Does an interface extend an interface? Does an abstract class implement an interface? Can an abstract class inherit a Concrete class? A: Interfaces can inherit from interfaces, and multiple inheritance is supported. Abstract classes can implement interfaces, and abstract classes can inherit from concrete classes as well as abstract classes.

33. Can a”.java” source file contain multiple classes (not inner classes)? What are the restrictions? A: Yes, but there can be at most one public class in a source file and the file name must be exactly the same as the public class name.

Can Anonymous Inner classes inherit from other classes? Can interfaces be implemented? A: You can inherit from other classes or implement other interfaces, which is common in Swing programming and Android development for event listening and callbacks.

35. Can an inner class reference a member of its containing class? Are there any restrictions? A: An inner class object can access the members of the outer class object that created it, including private members.

What are the uses of the final keyword in Java? A: (1) Modify class: indicates that the class cannot be inherited; (2) modification method: indicates that the method cannot be overwritten; (3) Modified variable: indicates that the value of a variable can only be assigned once and cannot be modified (constant).

37, Indicate the results of the following program.

class A { static { System.out.print("1"); } public A() { System.out.print("2"); } } class B extends A{ static { System.out.print("a"); } public B() { System.out.print("b"); } } public class Hello { public static void main(String[] args) { A ab = new B(); ab = new B(); }}Copy the code

A: Execution result: 1a2B2B. Object constructors are called in the order of initializing static members, then calling the parent class constructor, then initializing non-static members, and finally calling its own constructor.

Note: If you cannot give the correct answer to this question, you have not fully understood the Java class loading mechanism.

Conversion between data types: – How to convert a string to a primitive data type? – How to convert a primitive data type to a string? A: – Call the methods parseXXX(String) or valueOf(String) in the wrapper class corresponding to the base data type to return the corresponding base type; – One way is to concatenate a primitive data type with an empty string (“”) (+) to obtain its corresponding string; The alternative is to call the valueOf() method in the String class to return the corresponding String

39, how to achieve string inversion and replacement? A: many methods, can write their own implementation also can use the method in the String and StringBuffer/StringBuilder. A common interview question is to recursively invert a string, as shown below:

    public static String reverse(String originStr) {
        if(originStr == null || originStr.length() <= 1) 
            return originStr;
        return reverse(originStr.substring(1)) + originStr.charAt(0);
    }Copy the code

40. How to convert GB2312 encoded string to ISO-8859-1 encoded string? A: The code is as follows:

String s1 = "hello "; String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");Copy the code

41, Date and time: – How to get year month day, hour minute second? – How to obtain the number of milliseconds from 00:00:00:00 on January 1, 1970 to the present? – How do I get the last day of a month? – How to format dates? A: Problem 1: Create java.util.calendar instance and call its get() method to pass in different parameters to get the corresponding values of the parameters. This can be obtained in Java 8 using java.time.localDateTimel, as shown below.

public class DateTimeTest {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance()
        System.out.println(cal.get(Calendar.YEAR))
        System.out.println(cal.get(Calendar.MONTH))
        System.out.println(cal.get(Calendar.DATE))
        System.out.println(cal.get(Calendar.HOUR_OF_DAY))
        System.out.println(cal.get(Calendar.MINUTE))
        System.out.println(cal.get(Calendar.SECOND))

        // Java 8
        LocalDateTime dt = LocalDateTime.now()
        System.out.println(dt.getYear())
        System.out.println(dt.getMonthValue())
        System.out.println(dt.getDayOfMonth())
        System.out.println(dt.getHour())
        System.out.println(dt.getMinute())
        System.out.println(dt.getSecond())
    }
}Copy the code

Problem 2: The number of milliseconds can be obtained by any of the following methods.

Calendar.getInstance().getTimeInMillis()
System.currentTimeMillis()
Clock.systemDefaultZone().millis()Copy the code

Problem 3: The code is shown below.

Calendar time = Calendar.getInstance()
time.getActualMaximum(Calendar.DAY_OF_MONTH)Copy the code

Problem 4: Use the format(Date) method in a subclass of java.text.DataFormat, such as the SimpleDateFormat class, to format a Date. Java 8 can be used in Java. Time. The format. DateTimeFormatter to format the date time, code as shown below.

import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Date

class DateFormatTest {

    public static void main(String[] args) {
        SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd")
        Date date1 = new Date()
        System.out.println(oldFormatter.format(date1))

        // Java 8
        DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd")
        LocalDate date2 = LocalDate.now()
        System.out.println(date2.format(newFormatter))
    }
}Copy the code

Supplement: Java’s date and time API has been criticized for a long time. To address this problem, Java 8 introduced a new date and time API, including classes LocalDate, LocalTime, LocalDateTime, Clock, Instant, and so on. These classes are designed to use immutable patterns and are therefore thread-safe. If you don’t understand this, please refer to my other article, Summary and Thoughts on Concurrent Programming in Java.

Print the current moment of yesterday. A:

import java.util.Calendar

class YesterdayCurrent {
    public static void main(String[] args){
        Calendar cal = Calendar.getInstance()
        cal.add(Calendar.DATE, -1)
        System.out.println(cal.getTime())
    }
}Copy the code

In Java 8, you can implement the same functionality with the following code.

import java.time.LocalDateTime; class YesterdayCurrent { public static void main(String[] args) { LocalDateTime today = LocalDateTime.now(); LocalDateTime yesterday = today.minusDays(1); System.out.println(yesterday); }}Copy the code

Compare Java with JavaSciprt. A: JavaScript and Java are two different products developed by two companies. Java is an object-oriented programming language developed by Sun Microsystems, which is especially suitable for Internet application development. JavaScript is a Netscape product, developed to extend the capabilities of the Netscape browser, an object – and event-driven interpretive language that can be embedded in Web pages. JavaScript’s predecessor is LiveScript; Java’s predecessor is the Oak language. Java is a true object-oriented language. Even to develop simple programs, you must design objects. JavaScript is a scripting language that can be used to create complex software that interacts with users independently of the web. It is an object-based and event-driven programming language, so it itself provides a very rich internal objects for designers to use. – Interpret and compile: Java source code must be compiled before it can be executed. JavaScript is an interpreted programming language in which the source code is interpreted and executed by the browser without compilation. – Strongly typed variables and weakly typed variables: Java uses strongly typed variable checking, which means that all variables must be declared before compilation; Variables in JavaScript are weakly typed and may not even be declared before they are used, and the JavaScript interpreter checks at run time to infer their data type. – Different code formats.

P.S. The four points listed above are the so-called standard answers circulating on the Internet. The most important difference between Java and JavaScript is that one is a static language and the other is a dynamic language. At present, the development trend of programming language is functional language and dynamic language. Classes are first-class citizens in Java and functions are first-class citizens in JavaScript, so JavaScript supports functional programming, using Lambda functions and closures, and of course Java 8 is starting to support functional programming. Provides support for Lambda expressions as well as functional interfaces. For this kind of question, it is better to answer in your own language during the interview, rather than the so-called standard answer on the Internet.

44. When do you use assertions? A: Assertions are a common way of debugging in software development and are supported in many development languages. In general, assertions are used to guarantee the most fundamental, critical correctness of a program. Assertion checking is usually turned on during development and testing. Assertion checking is usually turned off after software is released to ensure efficient program execution. An assertion is a statement containing a Boolean expression that is assumed to be true when executed; If the value of the expression is false, an AssertionError is reported. The use of assertions is shown in the following code:

assert(a > 0); // throws an AssertionError if a <= 0Copy the code

Assertions can take two forms: assert Expression1; assert Expression1 : Expression2 ; Expression1 should always produce a Boolean value. Expression2 can be an arbitrary expression that yields a value; This value is used to generate string messages that show more debugging information.

To enableassertions at run time, use the -enableassertions or -ea flag when starting the JVM. To choose to disableassertions at run time, use the -da or -disableassertions tag when starting the JVM. To enable or disable assertions in system classes, use the -ESA or -dSA flags. Assertions can also be enabled or disabled on a package basis.

Note: Assertions should not change the state of the program in any way. Simply put, if you want to prevent code from executing if some condition is not met, you can consider blocking it with assertions.

45, What is the difference between Error and Exception? A: Error represents system-level errors and exceptions that the program does not have to handle, and is a serious problem in cases where recovery is not impossible but difficult; You can’t expect your program to handle an overflow of memory, for example; Exception is an Exception that needs to be caught or handled by a program. It is a design or implementation problem. That is, it represents a situation that would never happen if the program worked properly.

In 2005, MOTOROLA asked “If a process reports a stack overflow run-time error, what’s the most possible cause?” A. lack of memory; b. write on an invalid memory space; c. recursive function calling; C. Array index out of boundary. Java may also experience a StackOverflowError at runtime. If you write a recursion that does not converge quickly, it is likely to cause a stack overflow error, as shown below:

class StackOverflowErrorTest { public static void main(String[] args) { main(null); }}Copy the code

Tip: Keep two things in mind when writing recursively: 1. 2. Convergence conditions (when to stop recursion).

46. Will the code in finally{} immediately after a try{} be executed and when, before or after the return statement? A: It does, before the method returns to the caller.

Note: It is bad to change the return value in finally, because if there is a finally block, the return statement in try does not return the caller immediately. Instead, it records the return value and returns it to the caller after the finally block is finished executing. Then, if the return value is changed in finally, The modified value is returned. Obviously, returning or modifying a return value in finally can cause a lot of trouble for a program. C# uses compiler errors to prevent programmers from doing the dirty work. Java can also raise the compiler’s syntax checking level to generate warnings or errors. It is highly recommended that this be set to a compilation error.

Java language how to handle exceptions, keywords: throws, throw, try, catch, finally respectively how to use? A: Java takes an object-oriented approach to exception handling, classifying different exceptions and providing a good interface. In Java, each exception is an object that is an instance of the Throwable class or a subclass of it. When an exception occurs in a method, an exception object is thrown. This object contains the exception information, and the method calling this object can catch the exception and handle it. Java exception handling is implemented with five keywords: try, Catch, throw, throw, and finally. The usual way to execute a program is to try. If the system throws an exception object, it can catch it by its type, or it can handle it by always executing a block of code (finally). Try is used to specify a piece of the program to prevent all exceptions; The catch clause, immediately after the try block, specifies the type of exception you want to catch; The throw statement is used to explicitly throw an exception; Throws throws. Throws is used to declare the various exceptions that a method may throw. Finally To ensure that a piece of code will be executed no matter what exception occurs; Try statements can be nested, and each time a try statement is encountered, the structure of the exception is placed on the exception stack until all try statements are complete. If the next level of try does not handle an exception, the exception stack executes out of the stack until either a try statement is encountered to handle the exception or the exception is finally thrown to the JVM.

What are the similarities and differences between runtime anomalies and checked anomalies? A: An exception is an abnormal state that may occur during the running of a program. A runtime exception is an exception that may occur during the common operation of a VM. It is a common operation error that will not occur as long as the program is designed without any problems. Checked exceptions are related to the context in which the program is running. Even if the program is designed correctly, it can still be caused by problems in use. The Java compiler requires methods to declare to throw checked exceptions that can occur, but not run-time exceptions that are not caught. Exceptions, like inheritance, are often abused in object-oriented programming, and the following guidelines guide the use of exceptions in Effective Java: – Do not use exception handling for normal control flow (a well-designed API should not force its callers to use exceptions for normal control flow) – use checked exceptions for situations that can be recovered, Use runtime exceptions for programming errors – avoid unnecessary use of checked exceptions (exceptions can be avoided by means of state checking) – use standard exceptions in preference – document exceptions thrown by each method – keep exceptions atomic – do not ignore caught exceptions in a catch

49, List some of your common runtime exceptions. A: – ArithmeticException (ArithmeticException) – ClassCastException (class conversion exception) – IllegalArgumentException (IllegalArgumentException) – IndexOutOfBoundsException (subscript cross-border exception) – NullPointerException (null pointer exception) – SecurityException (security)

50. Explain the differences between final, finally and Finalize. A: -final: The modifier (keyword) can be used in three ways: If a class is declared final, it means that it cannot be subclassed, that is, it cannot be inherited, so it is the opposite of abstract. Declaring variables final guarantees that they will not be changed in use. Variables declared final must be given an initial value at the time of declaration and can only be read in future references. Methods declared final are also available only and cannot be overridden in subclasses. – finally: Usually placed in try… The catch… The following construct always executes a code block, which means that the program executes normally or when an exception occurs. The code here will execute as long as the JVM is not shut down. -Finalize: A method defined in the Object class that allows Java 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 objects are destroyed, and can be used to clean up system resources or do other cleanup work by overriding finalize().

51. Class ExampleA inherits Exception and class ExampleB inherits ExampleA. There is the following code snippet:

Try {throw new ExampleB("b")} catch (ExampleA e) {system.out.println ("ExampleA"); } catch (Exception e) {system.out.println ("Exception"); }Copy the code

What is the output of executing this code? Answer: Output: ExampleA. (According to the Richter substitution principle, catching a catch block of ExampleA type exceptions can catch an exception of ExampleB type thrown in a try block.)

Interview question – State the result of running the following code. (This question comes from the book Java Programming Ideas)

class Annoyance extends Exception {} class Sneeze extends Annoyance {} class Human { public static void main(String[] args) throws Exception { try { try { throw new Sneeze(); } catch ( Annoyance a ) { System.out.println("Caught Annoyance"); throw a; } } catch ( Sneeze s ) { System.out.println("Caught Sneeze"); return ; } finally { System.out.println("Hello World!" ); }}}Copy the code

Do List, Set, Map inherit from Collection interface? A: List and Set are correct, but Map is not. A Map is a key-value mapping container, distinct from a List or Set, which stores discrete elements and does not allow duplicate elements (the same is true of sets in mathematics). A List is a linear container, suitable for accessing elements by numerical index.

53. Explain the storage performance and features of ArrayList, Vector and LinkedList. A: ArrayList and Vector both store data in arrays that have more elements than the actual number of stored data to add and insert elements. They both allow elements to be indexed directly by ordinal number. However, inserting elements involves memory operations such as moving array elements, so indexing data is fast and inserting data is slow. The methods in Vector are thread-safe, thanks to the synchronized modifier, but perform worse than ArrayList and are already legacy containers in Java. LinkedList USES two-way linked list to achieve storage (memory scattered memory unit by attaching the reference, can form a linear structure according to the serial number index, the chain store mode compared with continuous storage arrays, memory utilization is higher), according to the serial number prior to or after the index data needed to traverse, However, only the items before and after the item need to be recorded when inserting data, so the insertion speed is fast. Vector is a legacy container (provided in earlier versions of Java, along with Hashtable, Dictionary, BitSet, Stack, and Properties) and is no longer recommended. But because ArrayList and LinkedListed are both non-thread-safe, if you have multiple threads working on the same container, It can then be converted into thread-safe containers through the synchronizedList method in the utility class Collections (this is an application of the decorator pattern, which enhances the implementation by passing existing objects into another class’s constructor to create new objects).

Supplement: Properties is a special key-value pair mapping with both keys and values as strings. It should be designed to associate a Hashtable and set its two generic parameters to String. But Properties in the Java API directly inherits Hashtable, which is an obvious abuse of inheritance. On the other hand, containers belong to utility classes. It Is A mistake to inherit utility classes. The best way to Use utility classes Is to Use HAS-A relationships (associations) or use-A relationships (dependencies). Similarly, it is incorrect for Stack classes to inherit from Vector. Sun engineers also make this kind of stupid mistake, which makes people sigh.

What is the difference between Collections and Collections? A: Collection is an interface. It is the parent interface of sets, lists, etc. Collections is a utility class that provides a set of static methods to assist container operations, including searching for containers, sorting, thread-safety, and so on.

55, What are the characteristics of the List, Map, and Set interfaces when accessing elements? A: A List accesses elements by a specific index, and can have duplicate elements. A Set cannot hold duplicate elements. (Use the equals() method of objects to tell if elements are duplicated.) Map stores key-value pair mappings. The mappings can be one-to-one or many-to-one. Both Set and Map containers have two implementation versions based on hash storage and sort tree. The theoretical access time complexity of the version based on hash storage is O(1), while the implementation based on sort tree will form a sort tree according to elements or their keys when inserting or deleting elements, so as to achieve the effect of sorting and de-duplicating.

56. How do TreeMap and TreeSet compare elements when sorting? How does the sort() method in the Collections utility class compare elements? A: TreeSet requires that the class to which the object belongs implement the Comparable interface, which provides a compareTo() method for comparing elements that is called back to compare their size when they are inserted. TreeMap requires that the keys of a stored key-value pair map implement the Comparable interface to sort elements by key. The Sort method of the Collections utility class takes two forms of overloading. The first requires the comparison of objects held in the incoming containers to be sorted to implement the Comparable interface for the comparison of elements. The second, non-mandatory, requires that the elements in the container be comparable, but requires passing in a second argument that is a subtype of the Comparator interface (the compare method needs to be overridden to compare elements). It is also an application of the callback pattern (Java’s support for functional programming). Example 1:

public class Student implements Comparable { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @Override public int compareTo(Student o) { return this.age - o.age; }}Copy the code
import java.util.Set; import java.util.TreeSet; class Test01 { public static void main(String[] args) { Set set = new TreeSet<>(); set.add(new Student("Hao LUO", 33)); set.add(new Student("XJ WANG", 32)); set.add(new Student("Bruce LEE", 60)); set.add(new Student("Bob YANG", 22)); for(Student stu : set) { System.out.println(stu); }}}Copy the code

Example 2:

public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() {return name; } public int getAge() {return age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; }}Copy the code
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; class Test02 { public static void main(String[] args) { List list = new ArrayList<>(); list.add(new Student("Hao LUO", 33)); list.add(new Student("XJ WANG", 32)); list.add(new Student("Bruce LEE", 60)); list.add(new Student("Bob YANG", 22)); Collections.sort(list, new Comparator () { @Override public int compare(Student o1, Student o2) { return o1.getName().compareTo(o2.getName()); }}); for(Student stu : list) { System.out.println(stu); }}}Copy the code

57, What is the difference between Thread’s sleep() and object’s wait() methods, which suspend execution? A: The sleep() method is a static method of the Thread class. Calling this method causes the current Thread to suspend execution for a specified time, giving up the CPU to another Thread. However, the lock on the object remains, so it is automatically resumed when the sleep time expires (the Thread returns to the ready state, See thread state transition diagram in question 66). Wait () is a method of the Object class. Calling the Object’s wait() method causes the current thread to abandon the lock on the Object and enter the Object’s wait pool. A thread in the wait pool can be awakened to enter the lock pool only when notify() (or notifyAll()) of an object is called. If the thread recaptures the lock of the object, it enters the ready state.

Add: Many people may be confused about what a process is and what a thread is, or why you need multithreaded programming. Simply said: process is a program with certain independent functions on a data set of a running activity, is an independent unit of the operating system for resource allocation and scheduling; A thread is an entity of a process, the basic unit of CPU scheduling and dispatching, and a smaller unit that can run independently than a process. The scale of thread partition is smaller than that of process, which makes the concurrency of multithreaded program high. Processes typically have separate memory units at execution, whereas threads can share memory. Programming using multithreading generally leads to better performance and user experience, but multithreaded programs are less friendly to other programs because they may consume more CPU resources. Of course, the more threads you have, the better your program will perform, because scheduling and switching between threads can also waste CPU time. Node.js, the most fashionable one, uses single-threaded asynchronous I/O.

What’s the difference between the sleep() method and the yield() method? The sleep() method gives other threads a chance to run without considering the priority of the thread, so it gives lower priority threads a chance to run. The yield() method only gives threads of the same or higher priority a chance to run; ② The thread is blocked after executing sleep() and ready after executing yield(). ③ The sleep() method declares to throw InterruptedException, while the yield() method does not declare any exceptions. ④ The sleep() method is more portable than the yield() method, which is related to operating system CPU scheduling.

59. When A thread enters the synchronized method A of an object, can other threads enter the synchronized method B of that object? A: No. Other threads can access only asynchronous methods of the object, and synchronized methods cannot. Since synchronized modifiers on non-static methods require that the object’s lock be acquired when executing the method, A thread that is already in method A must wait for the object’s lock to be taken, and A thread that is trying to enter method B must wait for the object’s lock in the pool.

Describe methods related to thread synchronization and thread scheduling. -wait () : causes a thread to wait(block) and releases the lock on its holding object; -sleep () : Puts a running thread to sleep, which is a static method that handles InterruptedException; -notify () : wakes up a thread that is in the wait state. This method is used to notify a thread that is in the wait state. -notityAll () : wakes up all threads in the waiting state. Instead of locking the object to all threads, they compete. Only the thread that acquired the lock can enter the ready state.

Tip: For Java multithreading and concurrent programming, I suggest you read my other article “Summary and Thoughts on Concurrent Programming in Java”.

Bonus: Java 5 provides explicit locking via the Lock interface for increased flexibility and thread coordination. The Lock interface defines methods for adding (Lock ()) and unlocking (unlock()). The newCondition() method is also provided to generate Condition objects for communication between threads. In addition, Java 5 provides semaphore, which can be used to limit the number of threads accessing a shared resource. Before accessing a resource, the thread must obtain permission from the Semaphore (call acquire() method on the Semaphore object); After completing access to the resource, the thread must return permission to the Semaphore (calling the Release () method of the Semaphore object).

The following example shows 100 threads simultaneously depositing 1 dollar into a bank account, both without and with synchronization.

Public class Account {private double balance; Public void deposit(double money) {double newBalance = balance + money; try { Thread.sleep(10); } catch(InterruptedException ex) { ex.printStackTrace(); } balance = newBalance; } public double getBalance() {return balance; }}Copy the code
/** * @author ** / public class addThread implements Runnable {private Account implements Runnable; private double money; public AddMoneyThread(Account account, double money) { this.account = account; this.money = money; } @Override public void run() { account.deposit(money); }}Copy the code
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test01 { public static void main(String[] args) { Account account = new Account(); ExecutorService service = Executors.newFixedThreadPool(100); for(int i = 1; i <= 100; i++) { service.execute(new AddMoneyThread(account, 1)); } service.shutdown(); while(! Service.isterminated ()) {} system.out.println (" account balance: "+ Account.getBalance ()); }}Copy the code

In the absence of synchronization, the results are often displayed account balance in 10 yuan, appear this kind of situation the reason is that when A thread A tries to deposit 1 yuan, another thread B can also deposit method, thread B read the account balance is still A thread A deposit account balance before 1 yuan, Thread C will do the same thing, so when the last 100 threads end up with an account balance of $100, they usually end up with less than $10 (probably $1). The solution to this problem is synchronization. When one thread deposits money into a bank account, it needs to lock the account and allow other threads to complete the operation. The code has the following adjustment schemes:

  • Synchronized keyword on the deposit method of a bank account
Public class Account {private double balance; Public synchronized void deposit(double money) {double newBalance = balance + money; try { Thread.sleep(10); } catch(InterruptedException ex) { ex.printStackTrace(); } balance = newBalance; } public double getBalance() {return balance; }}Copy the code
/** * @author ** / public class addThread implements Runnable {private Account implements Runnable; private double money; public AddMoneyThread(Account account, double money) { this.account = account; this.money = money; } @Override public void run() { synchronized (account) { account.deposit(money); }}}Copy the code
  • Using the locking mechanism shown in Java 5, create a lock object for each bank account to lock and unlock deposits
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author ** / public class Account {private Lock accountLock = new ReentrantLock(); private double balance; Public void deposit(double money) {accountLock.lock(); try { double newBalance = balance + money; try { Thread.sleep(10); } catch (InterruptedException ex) { ex.printStackTrace(); } balance = newBalance; } finally { accountLock.unlock(); }} /** * public double getBalance() {return balance; }}Copy the code

After modifying the code in the above three ways, rewrite the test code Test01 and see that the final account balance is $100. You can also use Semaphore or CountdownLatch for synchronization.

How many ways to write multithreaded programs? A: Java 5 used to implement multithreading in two ways: one was to inherit the Thread class; The other is to implement the Runnable interface. Either way, you override the run() method to define the behavior of a Thread. The latter is recommended because Java inheritance is single-inheritance. A class has a parent class, and if it inherits Thread, it cannot inherit other classes.

A third way to create threads after Java 5 is to implement the Callable interface, where the call method produces a return value at the end of thread execution, as shown below:

import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; class MyTask implements Callable { private int upperBounds; public MyTask(int upperBounds) { this.upperBounds = upperBounds; } @Override public Integer call() throws Exception { int sum = 0; for(int i = 1; i <= upperBounds; i++) { sum += i; } return sum; } } class Test { public static void main(String[] args) throws Exception { List> list = new ArrayList<>(); ExecutorService service = Executors.newFixedThreadPool(10); for(int i = 0; i < 10; i++) { list.add(service.submit(new MyTask((int) (Math.random() * 100)))); } int sum = 0; for(Future future : list) { sum += future.get(); } System.out.println(sum); }}Copy the code

62, Synchronized? A: The synchronized keyword marks an object or method as synchronized to achieve mutually exclusive access to the object or method. } defines blocks of synchronized code, or synchronized as a method modifier when declaring methods. The use of the synchronized keyword has been shown in the example in question 60.

63. Give examples of synchronization and asynchrony. Answer: if the system exists in the critical resources (resource quantity is less than the competition of the number of threads resources), such as data that is being written by another thread may be read, the data may have been or are in the read another thread to write, so these data must be synchronized access (exclusive lock is the best example of database operations). When your application calls a method on an object that takes a long time to execute, and you don’t want to leave your program waiting for the method to return, you should use asynchronous programming, which in many cases is more efficient. In fact, synchronous is a blocking operation and asynchronous is a non-blocking operation.

64. Do I call the run() or start() method to start a thread? A: To start a thread, call the start() method and make the virtual processor it represents runnable. This means that it can be scheduled and executed by the JVM. It does not mean that the thread will run immediately. The run() method is a callback to be performed after a thread is started.

What is a thread pool? A: In object-oriented programming, creating and destroying objects is time consuming because creating an object requires memory resources or more. This is especially true in Java, where the virtual machine will try to keep track of every object so that it can be garbage collected after the object is destroyed. So one way to improve the efficiency of a service application is to minimize the number of objects created and destroyed, especially those that are very expensive. This is where pooling resources comes in. Thread pool, as its name implies, is to create a number of executable threads in advance into a pool (container), when needed to obtain threads from the pool without creating their own, after use does not need to destroy threads but put back into the pool, thereby reducing the creation and destruction of thread objects overhead. The Executor interface in Java 5+ defines a tool for executing threads. Its subtype, the thread pool interface, is ExecutorService. It’s complicated to configure a thread pool, especially if the mechanism of the thread pool is not clear. So the following static factory methods are provided in the Executors section of the tool class: – newSingleThreadExecutor: Create a single thread pool. This thread pool has only one thread working, which is equivalent to a single thread executing all tasks in serial. If the unique thread terminates due to an exception, a new thread will replace it. This thread pool ensures that all tasks are executed in the order in which they were submitted. – newFixedThreadPool: creates a thread pool of a fixed size. A thread is created each time a task is submitted until the thread reaches the maximum size of the thread pool. The size of the thread pool stays the same once it reaches its maximum size, and if a thread terminates due to execution exceptions, a new thread is added to the pool. – newCachedThreadPool: creates a cacheable thread pool. If the size of the thread pool exceeds the number of threads needed to process the task, the pool can reclaim some of the idle (60-second non-executing) threads and intelligently add new threads to process the task as the number of tasks increases. This thread pool has no limit on the thread pool size, which is entirely dependent on the maximum thread size that the operating system (or JVM) can create. – newScheduledThreadPool: Creates a thread pool of unlimited size. This thread pool supports the need to execute tasks regularly and periodically. – newSingleThreadExecutor: Creates a single thread pool. This thread pool supports the need to execute tasks regularly and periodically.

Create a thread pool and use the thread pool to execute the thread using the Executors tool class. If you want to use thread pools on the server, the newFixedThreadPool method is strongly recommended to create thread pools for better performance.

What is the basic state of the thread and the relationship between the states?

A:

Description: The Running, Runnable, and Blocked states can occur as a result of calling a wait() method to enter the wait pool, or executing a synchronized method or code block to enter the isolock pool. Either the sleep() or Join () methods were called to wait for sleep or another thread to finish, or an I/O interrupt occurred.

67, briefly synchronized and Java. Util. Concurrent. The locks. The similarities and differences of the Lock? A: Lock is a new API introduced after Java 5. It has some similarities with the keyword synchronized: Lock does all the things synchronized does; Key differences: Lock has more precise thread semantics and better performance than synchronized, and it is not mandatory to acquire the Lock. Synchronized automatically releases locks, whereas locks must be released manually by the programmer and are best released ina finally block (which is the best place to release external resources).

68. How serialization is implemented in Java, and what does it mean? A: Serialization is a mechanism for dealing with streams of objects, that is, streaming the contents of objects. You can read and write the fluidized object or transfer the fluidized object between networks. Serialization is intended to solve problems that may occur when reading or writing objects (data may be out of order if not serialized). To implement serialization, you need to have a class that implements the Serializable interface, which is an identifier that marks the class objects as Serializable, and then uses an output stream to construct an Object output stream and write out the implementation Object(that is, save its state) using the writeObject(Object) method. If deserialization is required, an object input stream can be created with an input stream, and objects can be read from the stream using the readObject method. In addition to persisting objects, serialization can also be used for deep cloning of objects (see question 29).

How many types of flows are there in Java? Answer: Byte stream and character stream. The byte stream inherits from InputStream and OutputStream, and the character stream inherits from Reader and Writer. There are many other streams in the java.io package, mainly for performance and ease of use. There are two things to note about Java I/O: first, there are two symmetries (symmetry of input and output, byte and character); The second is two design modes (adapter mode and decoration mode). In addition, Java flows differ from C# in that they have only one dimension and one direction.

Interview question – Programming to implement file copy. (This question often appears in written exams, and the following code shows two implementations.)

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public final class MyUtil { private MyUtil() { throw new AssertionError(); } public static void fileCopy(String source, String target) throws IOException { try (InputStream in = new FileInputStream(source)) { try (OutputStream out = new FileOutputStream(target)) { byte[] buffer = new byte[4096]; int bytesToRead; while((bytesToRead = in.read(buffer)) ! = -1) { out.write(buffer, 0, bytesToRead); } } } } public static void fileCopyNIO(String source, String target) throws IOException { try (FileInputStream in = new FileInputStream(source)) { try (FileOutputStream out =  new FileOutputStream(target)) { FileChannel inChannel = in.getChannel(); FileChannel outChannel = out.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(4096); while(inChannel.read(buffer) ! = -1) { buffer.flip(); outChannel.write(buffer); buffer.clear(); } } } } }Copy the code

Note: Using THE Java 7 TWR above makes the code more elegant by not releasing external resources in finally.

Write a method that enters a file name and a string and counts the number of times the string appears in the file. A: The code is as follows:

import java.io.BufferedReader; import java.io.FileReader; public final class MyUtil { private MyUtil() { throw new AssertionError(); } /** * Count the number of occurrences of a given string in a given file ** @param filename filename * @param word string * @return Number of occurrences of a string in a given file */ public static int countWordInFile(String filename, String word) { int counter = 0; try (FileReader fr = new FileReader(filename)) { try (BufferedReader br = new BufferedReader(fr)) { String line = null; while ((line = br.readLine()) ! = null) { int index = -1; while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) { counter++; line = line.substring(index + word.length()); } } } } catch (Exception ex) { ex.printStackTrace(); } return counter; }}Copy the code

71, How to use Java code to list all files in a directory? A: If you only want to list files under the current folder, the code looks like this:

import java.io.File; class Test12 { public static void main(String[] args) { File f = new File("/Users/Hao/Downloads"); for(File temp : f.listFiles()) { if(temp.isFile()) { System.out.println(temp.getName()); }}}}Copy the code

If you need to expand the folder further, the code looks like this:

import java.io.File; class Test12 { public static void main(String[] args) { showDirectory(new File("/Users/Hao/Downloads")); } public static void showDirectory(File f) { _walkDirectory(f, 0); } private static void _walkDirectory(File f, int level) { if(f.isDirectory()) { for(File temp : f.listFiles()) { _walkDirectory(temp, level + 1); } } else { for(int i = 0; i < level - 1; i++) { System.out.print("\t"); } System.out.println(f.getName()); }}}Copy the code

In Java 7 you can use the NIo.2 API to do the same thing, as shown below:

class ShowFileTest { public static void main(String[] args) throws IOException { Path initPath = Paths.get("/Users/Hao/Downloads"); Files.walkFileTree(initPath, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println(file.getFileName().toString()); return FileVisitResult.CONTINUE; }}); }}Copy the code

Using Java socket programming to achieve a multithreaded echo server. A:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class EchoServer { private static final int ECHO_SERVER_PORT = 6789; public static void main(String[] args) { try(ServerSocket server = new ServerSocket(ECHO_SERVER_PORT)) { System.out.println(" Server started...") ); while(true) { Socket client = server.accept(); new Thread(new ClientHandler(client)).start(); } } catch (IOException e) { e.printStackTrace(); } } private static class ClientHandler implements Runnable { private Socket client; public ClientHandler(Socket client) { this.client = client; } @Override public void run() { try(BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter pw = new PrintWriter(client.getOutputStream())) { String msg = br.readLine(); System.out.println(" received "+ client.getinetAddress () +" sent: "+ MSG); pw.println(msg); pw.flush(); } catch(Exception ex) { ex.printStackTrace(); } finally { try { client.close(); } catch (IOException e) { e.printStackTrace(); } } } } }Copy the code

Note: The above code uses the Java 7 TWR syntax. Since many external resource classes implement the AutoCloseable interface indirectly (single-method callback interface), it is possible to use THE TWR syntax to call the close() method of the external resource class automatically at the end of the try. Avoid writing long finally blocks. In addition, the above code uses a static inner class to implement the threading function, using multithreading to prevent the interruption of one user’s I/O operation from affecting other users’ access to the server. Simply speaking, one user’s input operation will not cause other users to block. Of course, the above code gets better performance using thread pools, because the overhead of creating and destroying threads frequently is not negligible.

Here is a snippet of client test code that echoes:

import java.io.BufferedReader import java.io.InputStreamReader import java.io.PrintWriter import java.net.Socket import java.util.Scanner public class EchoClient { public static void main(String[] args) throws Exception { Socket client = New Socket("localhost", 6789) Scanner sc = new Scanner(system.in) system.out.print (" Please enter the content: ") String msg = sc.nextLine() sc.close() PrintWriter pw = new PrintWriter(client.getOutputStream()) pw.println(msg) pw.flush() BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream())) System.out.println(br.readLine()) client.close() } }Copy the code

If you want to implement a server using NIO’s multiplexed sockets, the code looks like this. NIO’s operations provide better performance, but some operations are low-level and difficult for beginners to understand.

import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; public class EchoServerNIO { private static final int ECHO_SERVER_PORT = 6789; private static final int ECHO_SERVER_TIMEOUT = 5000; private static final int BUFFER_SIZE = 1024; private static ServerSocketChannel serverChannel = null; private static Selector selector = null; private static ByteBuffer buffer = null; public static void main(String[] args) { init(); listen(); } private static void init() { try { serverChannel = ServerSocketChannel.open(); buffer = ByteBuffer.allocate(BUFFER_SIZE); serverChannel.socket().bind(new InetSocketAddress(ECHO_SERVER_PORT)); serverChannel.configureBlocking(false); selector = Selector.open(); serverChannel.register(selector, SelectionKey.OP_ACCEPT); } catch (Exception e) { throw new RuntimeException(e); } } private static void listen() { while (true) { try { if (selector.select(ECHO_SERVER_TIMEOUT) ! = 0) { Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); handleKey(key); } } } catch (Exception e) { e.printStackTrace(); } } } private static void handleKey(SelectionKey key) throws IOException { SocketChannel channel = null; try { if (key.isAcceptable()) { ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); channel = serverChannel.accept(); channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { channel = (SocketChannel) key.channel(); buffer.clear(); if (channel.read(buffer) > 0) { buffer.flip(); CharBuffer charBuffer = CharsetHelper.decode(buffer); String msg = charBuffer.toString(); System.out.println(" received "+ channel.getremoteAddress () +" : "+ MSG); channel.write(CharsetHelper.encode(CharBuffer.wrap(msg))); } else { channel.close(); } } } catch (Exception e) { e.printStackTrace(); if (channel ! = null) { channel.close(); }}}}Copy the code
import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; public final class CharsetHelper { private static final String UTF_8 = "UTF-8"; private static CharsetEncoder encoder = Charset.forName(UTF_8).newEncoder(); private static CharsetDecoder decoder = Charset.forName(UTF_8).newDecoder(); private CharsetHelper() { } public static ByteBuffer encode(CharBuffer in) throws CharacterCodingException{ return encoder.encode(in); } public static CharBuffer decode(ByteBuffer in) throws CharacterCodingException{ return decoder.decode(in); }}Copy the code

73. How many forms does an XML document definition take? What are the essential differences between them? What are some ways to parse AN XML document? A: XML document definitions are divided into DTD and Schema, both of which are constraints on XML syntax. The essential difference is that Schema itself is also an XML file, which can be parsed by XML parsers and can define types for the data carried by XML. The constraint capability is stronger than DTD. XML parsing includes DOM (Document Object Model), SAX (Simple API for XML) and StAX (Streaming API for XML, a new XML parsing method introduced in Java 6). This problem is caused by the large memory occupied by DOM tree structure. Moreover, DOM parsing must load the entire document into memory before parsing the file, which is suitable for random access to XML (typical strategy of buying time with space). SAX is an event-driven XML parsing method that reads XML files sequentially without loading the entire file at once. When it encounters things like the beginning of a file, the end of a document, or the beginning and end of a tag, it triggers an event, and the user processes the XML file through the event callback code, suitable for sequential access to the XML; As the name suggests, StAX focuses on streams, but the essential difference between StAX and other parsing approaches is that applications can process XML as a stream of events. The idea of processing XML as a set of events is not new (SAX does this), but the difference is that StAX allows application code to pull these events out one by one, rather than providing a handler that receives the events from the parser at its convenience.

74. Where did you use XML in your project? A: XML has two main functions: data exchange and information configuration. In data exchange, XML assembled data with tags, then compressed, packaged, encrypted and sent to the receiver over the network. After receiving decryption and decompression, relevant information was restored from XML files for processing. XML used to be the de facto standard for data exchange between heterogeneous systems. But this functionality has almost been replaced by JSON (JavaScript Object Notation). At present a lot of software, of course, still use XML to store configuration information, we will in many projects are usually as a hard-coded configuration information is written in the XML file, many of the Java framework did the same, and the framework, chose the dom4j as XML processing tools, because the Sun’s really not how to use the official API.

Add: With trendy software such as Sublime starting to write configuration files in JSON format, there is a strong sense that another aspect of XML is being abandoned by the industry.

75, describe the steps of JDBC database operation. A: The following code uses connecting to the local Oracle database as an example to demonstrate the steps of a JDBC database operation.

    Class.forName("oracle.jdbc.driver.OracleDriver");Copy the code
    Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");Copy the code
PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?" ); ps.setInt(1, 1000); ps.setInt(2, 3000);Copy the code
    ResultSet rs = ps.executeQuery();Copy the code
    while(rs.next()) {
        System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"))
    }Copy the code
finally { if(con ! = null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); }}}Copy the code

Note: External resources should be closed in the opposite order as they are opened. That is, close a ResultSet first, then a Statement, and then a Connection. The above code only closes the Connection, although normally when you close a Connection, statements created on the Connection and open cursors are also closed, but this is not always guaranteed, so you should close them separately in the order just described. In addition, the first step of loading the driver can be omitted in JDBC 4.0 (automatically loading the driver from the classpath), but we recommend keeping it.

76. What is the difference between a Statement and PreparedStatement? Which has better performance? PreparedStatement (PreparedStatement) is a PreparedStatement interface. PreparedStatement (PreparedStatement) is a PreparedStatement interface. PreparedStatement (PreparedStatement) is a PreparedStatement interface. (2) SQL statements in PreparedStatement can be prepared with parameters, avoiding the trouble and insecurity of using string concatenation SQL statements; (3) PreparedStatements have obvious performance advantages when batch processing SQL or frequently executing the same query. Preparedstatements can be cached by the database, and the next time a statement with the same structure is executed, it will be faster (no need to compile and generate an execution plan again).

Note: To provide calls to stored procedures, the JDBC API also provides the CallableStatement interface. Stored Procedure is a set of SQL statements in a database to complete a specific function. After being compiled, it is Stored in the database. The user can execute the Stored Procedure by specifying its name and giving parameters (if the Stored Procedure has any parameters). Although there are many benefits to calling stored procedures in terms of network overhead, security, and performance, there is a lot of trouble if the underlying database is migrated, because the stored procedures of each database are written differently.

When using JDBC to operate database, how to improve the performance of reading data? How to improve the performance of updated data? A: To improve the performance of reading data, you can specify the number of records fetched each time through the setFetchSize() method of a ResultSet object (a typical space-time strategy). To improve the performance of updated data, you can build a batch using the PreparedStatement statement, in which several SQL statements are executed in a batch.

78, What is the role of connection pool in database programming? A: Due to create connections and release the connection has great overhead (especially the database server is not local, every time requires a connection is established the TCP three-way handshake, release the connection needs to be TCP handshake, four times the overhead is not to be ignored), in order to improve the performance of the system to access the database, can create a number of connections in the connection pool in advance, Fetching directly from the connection pool when needed and returning the connection pool at the end of use without having to close the connection avoids the overhead of frequently creating and releasing connections, which is a typical space-for-time strategy (wasting space storing connections, but saving time creating and releasing connections). Pooling techniques are common in Java development, and the same is true for creating thread pools when using threads. Java based open source database connection pools include C3P0, Proxool, DBCP, BoneCP, Druid, and so on.

Addendum: Understanding that time and space are irreconcilable contradictions in computer systems is crucial to designing algorithms that meet performance requirements. One key to optimizing the performance of large sites is the use of caching, which is a space-for-time strategy very similar to the connection pooling principle described above. You can put hot data in the cache and get it directly from the cache when the user queries it, which is faster than the database query anyway. Of course, cache substitution strategies and so on can also have a significant impact on system performance, which is beyond the scope of this discussion.

What is the DAO pattern? A: DAO (Data Access Object), as its name implies, is an Object that provides an abstract interface for a database or other persistence mechanism. It provides various Data Access operations without exposing the implementation details of the underlying persistence scheme. In real development, all access operations to the data source should be abstracted and encapsulated in a common API. In programming languages, this is to create an interface that defines all the transaction methods that will be used in the application. In this application, this interface is used when you need to interact with the data source, and a separate class is written to implement this interface, which logically corresponds to a specific data store. DAO mode actually contains two modes, one is Data Accessor (Data Accessor) and the other is Data Object (Data Object). The former is to solve the problem of how to access Data, while the latter is to solve the problem of how to encapsulate Data with objects.

What is transaction ACID? – Atomic: all operations in a transaction can be done or not done at all. Failure of any operation will result in failure of the whole transaction. – Consistent: The system status is Consistent after a transaction. – Isolation: Concurrently executed transactions cannot see the intermediate state of each other. – Durable: Changes made after transactions are Durable, even if catastrophic failures occur. Log and synchronous backups can be used to rebuild data after a failure.

P.S. Regarding business matters, the probability of being asked in an interview is very high, and there are many questions to ask. The first thing to know is that transactions are only required if there is concurrent data access. When multiple transactions access the same data, there may be five types of problems, including type 3 data read problems (dirty reads, non-repeatable reads, and phantom reads) and type 2 data update problems (Type 1 missing updates and Type 2 missing updates).

Dirty Read: When transaction A reads uncommitted data from transaction B and operates on it, and transaction B rolls back, the data Read by transaction A is Dirty.

time Transfer Transaction A Withdrawal transaction B
T1   Start the transaction
T2 Start the transaction  
T3   The query account balance is 1000 yuan
T4   Take out $500 and change the balance to $500
T5 Query account balance is 500 yuan (dirty read)  
T6   Undo transaction balance restored to $1000
T7 Remit 100 yuan to change the balance to 600 yuan  
T8 Commit the transaction  

Unrepeatable Read: transaction A re-reads the previously Read data and finds that the data has been modified by another committed transaction B.

time Transfer Transaction A Withdrawal transaction B
T1   Start the transaction
T2 Start the transaction  
T3   The query account balance is 1000 yuan
T4 The query account balance is 1000 yuan  
T5   Take out $100 to change the balance to $900
T6   Commit the transaction
T7 Query account balance is 900 yuan (not repeatable)  

Phantom Read: Transaction A re-executes A query, returns A list of rows that match the query criteria, and finds inserted rows that were committed by transaction B.

time Statistical amount transaction A Transfer transaction B
T1   Start the transaction
T2 Start the transaction  
T3 The total deposit is 10000 yuan  
T4   Open a savings account and deposit 100 yuan
T5   Commit the transaction
T6 The total deposit is 10100 YUAN.  

Type 1 Missing updates: When transaction A is revoked, the updated data of the committed transaction B is overwritten.

time Withdrawal transaction A Transfer transaction B
T1 Start the transaction  
T2   Start the transaction
T3 The query account balance is 1000 yuan  
T4   The query account balance is 1000 yuan
T5   Remit 100 yuan to change the balance to 1100 yuan
T6   Commit the transaction
T7 Take out $100 and change the balance to $900  
T8 Cancel the transaction  
T9 Balance restored to 1000 yuan (lost update)  

Type 2 missing update: Transaction A overwrites the data already committed by transaction B, causing the operations done by transaction B to be lost.

time Transfer Transaction A Withdrawal transaction B
T1   Start the transaction
T2 Start the transaction  
T3   The query account balance is 1000 yuan
T4 The query account balance is 1000 yuan  
T5   Take out $100 and change the balance to $900
T6   Commit the transaction
T7 Remit 100 yuan to change the balance to 1100 yuan  
T8 Commit the transaction  
T9 Query account balance is 1100 yuan (lost update)  

The problem caused by concurrent data access may be allowed in some scenarios, but it may be fatal in some scenarios. Databases usually solve the problem by locking mechanism, which can be divided into table level locking and row level locking according to different locked objects. According to the concurrent transaction lock relationship can be divided into shared lock and exclusive lock, the specific content we can consult the information to understand. Directly using the lock is very troublesome, for this database provides users with automatic locking mechanism, as long as the user of the specified session transaction isolation level, the database will be based on the analysis of the SQL statement and then for the transaction to access resources, plus appropriate locks, in addition, the database will also maintain the lock through various means to improve the performance of the system, All of this is transparent to the user (which means you don’t have to understand, which I don’t). The ANSI/ISO SQL 92 standard defines four levels of transaction isolation levels, as shown in the following table:

Isolation level Dirty read Unrepeatable read Phantom read The first type is missing updates The second type of lost updates
READ UNCOMMITED allow allow allow Don’t allow allow
READ COMMITTED Don’t allow allow allow Don’t allow allow
REPEATABLE READ Don’t allow Don’t allow allow Don’t allow Don’t allow
SERIALIZABLE Don’t allow Don’t allow Don’t allow Don’t allow Don’t allow

It should be noted that the transaction isolation level and the concurrency of data access are antithetical, and the higher the transaction isolation level, the worse the concurrency. There is no one-size-fits-all rule for determining the appropriate transaction isolation level for your application.

How do transactions occur in JDBC?

A: Connection provides a method for transaction processing. You can set the transaction to commit manually by calling setAutoCommit(false). Commit () to explicitly commit the transaction when it completes; If an exception occurs during the transaction, the transaction is rolled back with rollback(). In addition, the concept of savepoints was introduced from JDBC 3.0, allowing you to set savepoints in code and roll back transactions to specified savepoints.

Can JDBC handle BLOBs and CLOBs? A: Blob stands for Binary Large Object and Clob stands for Character Large Objec, so BLOBs are designed to store Large Binary data and CLOBs are designed to store Large textual data. Both JDBC PreparedStatement and ResultSet provide methods to support Blob and Clob operations. MySQL > create a user table with three columns (id, name, photo);

create table tb_user
(
id int primary key auto_increment,
name varchar(20) unique not null,
photo longblob
);Copy the code

The following Java code inserts a record into the database:

import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; class JdbcLobTest { public static void main(String[] args) { Connection con = null; try { Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456"); PreparedStatement ps = con.prepareStatement("insert into tb_user values (default, ? ,?) "); Ps. SetString (1, "Luo Hao "); try (InputStream in = new FileInputStream("test.jpg")) { ps.setBinaryStream(2, in); System.out.println(ps.executeUpdate() == 1 ? "Insert succeeded" : "insert failed "); } catch(IOException e) {system.out.println (" Failed to read photo!" ); } } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } finally { try { if(con ! = null && ! con.isClosed()) { con.close(); con = null; } } catch (SQLException e) { e.printStackTrace(); }}}}Copy the code

83. Briefly describe regular expressions and their uses. Answer: When you write programs that work with strings, you often need to find strings that conform to some complex rules. Regular expressions are a tool for describing these rules. In other words, regular expressions are code that records rules for text.

Description: computer was born in the early processing of information are almost, but times have changed, today we use computer processing information more often rather than numeric string, the regular expression is in string matching and deal with the most powerful tools, most languages have provided support for regular expressions.

84. How are regular expression operations supported in Java? A: The String class in Java provides methods to support regular expression operations, including matches(), replaceAll(), replaceFirst(), and split(). In addition, regular expression objects can be represented in Java using the Pattern class, which provides a rich API for various regular expression operations. See the code in the interview question below.

Interview question: – If you want to extract the string before the first opening parenthesis from the string, for example: Beijing (Chaoyang District)(Xicheng District)(Haidian District), the result is: Beijing, then how to write the regular expression?

import java.util.regex.Matcher import java.util.regex.Pattern class RegExpTest { public static void main(String[] args) {String STR = "(chaoyang district), xicheng district of Beijing (haidian district)" the Pattern p = Pattern.com running (. *? "(? = \ \ ()") the Matcher m = p. atcher (STR) if (m. ind ()) { System.out.println(m.group()) } } }Copy the code

Note: Lazy matching and look-forward are used in regular expressions above. If you are not aware of these, you are recommended to read the popular 30-minute Tutorial on regular Expressions online.

What are the ways to get a class object of a class? A: – Method 1: type.class, for example: string.class – Method 2: object.getClass (), for example: “hello”.getClass() – Method 3: class.forname (), for example: Class.forName(“java.lang.String”)

How do I create objects with reflection? A: – Method 1: Calls newInstance() through the class object, for example: string.class.newinstance () – Method 2: Get the Constructor object from the class object’s getConstructor() or getDeclaredConstructor() method and call its newInstance() method to create the object, for example: String.class.getConstructor(String.class).newInstance(“Hello”);

How do I get and set the value of an object’s private field by reflection? A: The Field object can be set accessible by the getDeclaredField() method of the class object, and then by the setAccessible(true) method of the Field object. The value of the Field can then be set by the get/set method. The following code implements a reflection utility class with two static methods to get and set the value of a private field, which can be either a primitive or an object type and supports multi-level object operations, such as reflectionUtil.get (dog, “owner.car.engine.id”); You can get the engine ID of the dog object’s owner’s car.

import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; Public class ReflectionUtil {private ReflectionUtil() {throw new AssertionError(); @param Target Specifies the target object. @Param fieldName specifies the name of the field. @throws an exception if the value of the specified field cannot be retrieved public static Object getValue(Object target, String fieldName) { Class clazz = target.getClass(); String[] fs = fieldName.split("\\."); try { for(int i = 0; i < fs.length - 1; i++) { Field f = clazz.getDeclaredField(fs[i]); f.setAccessible(true); target = f.get(target); clazz = target.getClass(); } Field f = clazz.getDeclaredField(fs[fs.length - 1]); f.setAccessible(true); return f.get(target); } catch (Exception e) { throw new RuntimeException(e); @param target specifies the target object. @param fieldName specifies the name of the field. @param Value specifies the value setValue(Object target, String fieldName, Object value) { Class clazz = target.getClass(); String[] fs = fieldName.split("\\."); try { for(int i = 0; i < fs.length - 1; i++) { Field f = clazz.getDeclaredField(fs[i]); f.setAccessible(true); Object val = f.get(target); if(val == null) { Constructor c = f.getType().getDeclaredConstructor(); c.setAccessible(true); val = c.newInstance(); f.set(target, val); } target = val; clazz = target.getClass(); } Field f = clazz.getDeclaredField(fs[fs.length - 1]); f.setAccessible(true); f.set(target, value); } catch (Exception e) { throw new RuntimeException(e); }}}Copy the code

How do I call a method on an object through reflection? A: Look at the following code:

import java.lang.reflect.Method; class MethodInvokeTest { public static void main(String[] args) throws Exception { String str = "hello"; Method m = str.getClass().getMethod("toUpperCase"); System.out.println(m.invoke(str)); }}Copy the code

89. Briefly describe the “six principles and one Law” of object orientation. A: – Single responsibility principle: A class only does what it’s supposed to do. Want to express (single responsibility principle is “high cohesion,” write code the ultimate principle only six words “high cohesion and low coupling”, or to ward off bad luck is like sunflower treasure dian jian spectrum is the center of the eight words “before this work will be the first palace”, the so-called high cohesion is only a code module to complete a function, in the object-oriented, if only to make a class do it should do, By not touching areas that are not relevant to it, we are practicing the principle of high cohesion, so that the class has only one responsibility. We all know the phrase “focus is the key”, and if a subject takes on too many responsibilities, it is doomed to do nothing well. Any good thing in the world has two characteristics. One is that it has a single function. A good camera is definitely not the one sold in TV shopping. The other is a modular, a good bicycle is hard, from suspension fork and the brakes to the transmission, of all the parts can be disassembled and reassembled, good table tennis racket is not finished, must be a base plate and the rubber can be split and self-assembly, a good software system, it’s each function module should be also can easily get used in other systems, In this way, the goal of software reuse can be achieved. – Open closed principle: software entities should be open for extension and closed for modification. In an ideal world, when we need to add new functionality to a software system, we can simply derive new classes from the original system without changing a single line of code. (1) Abstraction is the key. If there is no abstract class or interface in a system, there is no extension point. (2) Encapsulate variability, encapsulate various variable factors in the system into an inheritance structure. If multiple variable factors are mixed together, the system will become complicated and chaotic. If it is not clear how to encapsulate variability, you can refer to the chapter on bridge mode in the book “Design Mode Refinement”. – Dependency inversion principle: Interface oriented programming. (When declaring method parameter types, method return types, and variable reference types, use abstract types instead of concrete types. Abstract types can be replaced by any of their subtypes. See The Richter substitution rule below.) Richter’s substitution principle: You can replace a parent type with a child type at any time. (Mrs. Barbara Liskov’s description of The Richter substitution principle is much more complex than this, but simply states that where a parent type can be used, a child type can be used. The Richter substitution principle checks whether the inheritance relationship is reasonable. If an inheritance relationship violates the Richter substitution principle, then the inheritance relationship must be wrong and the code needs to be refactured. For example, having a cat inherit from a dog, or a dog inherit from a cat, or a square inherit from a rectangle is a false inheritance, because you can easily find situations that violate The Richter’s substitution principle. Note that subclasses must increase the power of the parent class rather than decrease the power of the parent class, because subclasses have more power than the parent class, and there is no problem using objects with more power as objects with less power. – Interface isolation principle: The interfaces should be small and specialized, but not large and complete. (Bloated interfaces pollute interfaces. Since interfaces represent capabilities, an interface should only describe one capability, and interfaces should be highly cohesive. Unique romance, for example, should be designed respectively for four interface, and should not be designed as an interface of the four methods, as if designed into four methods in an interface, the interface is difficult to use, unique romance, after all, four are proficient in one or a few, and if the design into four interface, would achieve several several interfaces, The likelihood of each interface being reused is high. In Java, interface represents ability, convention and role. Whether the interface can be used correctly must be an important indicator of programming level. – Composite aggregation reuse principle: use aggregation or composite relationship reuse code is preferred. (through inheritance to copy code Is being abused at most in object-oriented programming, because all the textbooks without exception to preach to mislead beginners, inheriting classes with simple says there are three kinds of relationships between classes, Is A relationship, Has A relationship, Use – A relationship, represent the inheritance, association and dependency. Among them, association relation can be further divided into association, aggregation and synthesis according to the strength of its association, but all of them are HAS-A relation, and the principle of composite polymerization reuse wants to express that HAS-A relation Is given priority over IS-A relation reuse code. The reason can be found in Baidu for 10,000 reasons. It needs to be explained that: Even in Java apis, there are examples of inheritance abuse, such as Properties inheriting from Hashtable and Stack inheriting from Vector, which are clearly wrong. It would be better to put a Hashtable member in the Properties class and set its keys and values to strings to store the data, while the Stack class would be designed to put a Vector in the Stack class to store the data. Remember: never inherit utility classes. Tools are owned and used, not inherited. – Demeter’s Law: Also known as the least Knowledge principle, one object should know as little as possible about other objects. (Demeter’s Law is simply how to achieve “low coupling”, and the facade mode and the mediator mode are the practice of Demeter’s law. For facade pattern can cite a simple example, you go to a company to negotiate business, you don’t need to understand how this company works, you can even do not know anything about this company, only need to find the front desk at the entrance of the company when he went to the beauty, tell them you want to do, they will find the right person contact with you, The beauty at the front desk is the face of the system. Any complex system can provide a simple facade for the user. A Servlet or Filter, as a front-end controller in Java Web development, is a facade. The browser does not know how the server works, but the front-end controller can get the corresponding service according to your request. Mediator pattern can also be a simple example to illustrate how, for example, a computer, CPU, memory, hard disk, video card, sound card, all kinds of equipment need to cooperate with one another to be a very good job, but if all the things are directly connected to the computer wiring will be complicated, in this case, the main board have emerged as a mediator, It connects devices together without the need to exchange data directly between each device, thus reducing the coupling and complexity of the system, as shown in the figure below. In layman’s terms, Demeter’s Law would be to avoid strangers, and if you really need to, find a friend and let him do the strangers for you.)



90. Briefly describe the design patterns you understand. A: A design pattern is a set of code design lessons that have been used over and over again (a proven solution to a problem in a situation). Design patterns are used to re-use code, make it easier for others to understand, and ensure code reliability. Design patterns make it easier to reuse successful designs and architectures. Expressing proven technologies as design patterns also makes it easier for developers of new systems to understand their design ideas. Design Patterns at GoF: Elements of Reusable Object-Oriented Software presents three types of design patterns (creative [abstraction of the instantiation process of a class], structural [description of how classes or objects are joined together to form a larger structure], and behavioral [abstraction of assigning responsibilities and algorithms between different objects]). There are 23 design patterns, including: Abstract Factory, Builder, Factory Method, Prototype, Singleton; Facade, Adapter, Bridge, Composite, Decorator, Flyweight, Proxy; Facade, Adapter, Bridge, Composite, Decorator, Flyweight, Proxy; A Command, an Interpreter, a Visitor, an Iterator, a Mediator, a Memento, an Observer, a Visitor, an Interpreter, a Visitor, an Iterator, a Mediator, a Memento, an Observer, a Mediator. State, Strategy, Template Method, Chain Of Responsibility. Interview when asked about design patterns, you can pick the most common answer, for example: – factory pattern: the factory class can be generated according to the condition of different subclass instances, these children have a common abstract parent class and implement the same method, but these methods according to different data for different operation (polymorphic methods). Once you have an instance of a subclass, the developer can call a method in the base class regardless of which instance of the subclass is being returned. – Proxy mode: An object is provided with a proxy object and the proxy object controls references to the original object. In actual development, according to different purposes, agents can be divided into: remote proxy, virtual proxy, protection proxy, Cache proxy, firewall proxy, synchronization proxy, intelligent reference proxy. – Adapter mode: Transforms the interface of a class into another interface expected by the client, so that classes that cannot be used together due to interface mismatches can work together. – Template method pattern: Provides an abstract class that implements some of the logic as concrete methods or constructors, and then declares some abstract methods to force subclasses to implement the rest of the logic. Different subclasses can implement these abstract methods (polymorphic implementations) in different ways to implement different business logic. In addition, you can also talk about the facade pattern, the bridge pattern, the singleton pattern, the decoration pattern (used in the Collections utility class and I/O system) mentioned above, etc. Anyway, the basic principle is to pick the most familiar and used ones, so as not to miss the point.

Write a singleton class in Java. A: – Hungry singleton

public class Singleton { private Singleton(){} private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; }}Copy the code
public class Singleton { private static Singleton instance = null; Private Singleton() {} public static synchronized getInstance(){if (instance == null) instance = new Singleton(); return instance; }}Copy the code

Note: There are two points to note when implementing a singleton: ① Make the constructor private and do not allow outsiders to create objects through the constructor; ② Return a unique instance of a class to the outside world via an exposed static method. Here’s a question to ponder: Spring’s IoC container can create singletons for ordinary classes. How does it do it?

What is UML? A: UML is short for Unified Modeling Language (UML). Published in 1997, UML combines existing object-oriented Modeling languages, methods, and processes. It is a graphical Language that supports Modeling and software system development. Provides modeling and visualization support for all phases of software development. Using UML can aid in communication and communication, aid in application design and documentation generation, and explain system structure and behavior.

What diagrams are commonly used in UML?

A: UML defines a variety of graphical notations to describe part or all of the static and dynamic structure of a software system, including: Use Case Diagram, Class Diagram, Sequence Diagram, Collaboration Diagram, Statechart Diagram, Activity diagram, Component diagram, Deployment diagram, etc. Among these graphical symbols, there are three diagrams that are the most important: Use case diagrams (used to capture requirements, describes the function of the system, through the picture can quickly understand the function modules of the system and their relationships), the class diagram (describe the relationship between class and class with class, through which can quickly understand system), sequence diagrams (describe the interactions between objects when performing a specific task and execution order, This diagram shows what messages an object can receive, that is, what services it can provide to the outside world.

Use case diagram:



Class diagram:



Sequence diagram:

Write a bubble sort in Java. A: Bubble sort is almost a programmer can write, but how to write a high bubble sort interview is not everyone can do, the following provides a reference code:

import java.util.Comparator; /** * collator interface (policy mode: Encapsulate the algorithm into a separate class with a common interface so that they can be interchangeable) * @author Lohao ** / public interface Sorter {/** ** sort * @param list array to sort */ public > void sort(T[] list); Public void sort(T[] list, Comparator comp); }Copy the code
import java.util.Comparator; Public class BubbleSorter implements Sorter {@override public > void sort(T[] list) { boolean swapped = true; for (int i = 1, len = list.length; i < len && swapped; ++i) { swapped = false; for (int j = 0; j < len - i; ++j) { if (list[j].compareTo(list[j + 1]) > 0) { T temp = list[j]; list[j] = list[j + 1]; list[j + 1] = temp; swapped = true; } } } } @Override public void sort(T[] list, Comparator comp) { boolean swapped = true; for (int i = 1, len = list.length; i < len && swapped; ++i) { swapped = false; for (int j = 0; j < len - i; ++j) { if (comp.compare(list[j], list[j + 1]) > 0) { T temp = list[j]; list[j] = list[j + 1]; list[j + 1] = temp; swapped = true; } } } } }Copy the code

Write a half search in Java. A: Split search, also known as binary search, binary search, is a search algorithm in an ordered array to find a particular element. The search process starts with the middle element of the array. If the middle element is exactly the element to be searched, the search process ends. If a particular element is greater than or less than the middle element, it looks in the half of the array that is greater than or less than the middle element, and compares from the middle element as it began. If the array is empty at any point, the specified element cannot be found. This search algorithm reduces the search scope by half with each comparison, and its time complexity is O(logN).

import java.util.Comparator; public class MyUtil { public static > int binarySearch(T[] x, T key) { return binarySearch(x, 0, x.length- 1, key); } public static int binarySearch(T[] x, T key, Comparator comp) { int low = 0; int high = x.length - 1; while (low <= high) { int mid = (low + high) >>> 1; int cmp = comp.compare(x[mid], key); if (cmp < 0) { low= mid + 1; } else if (cmp > 0) { high= mid - 1; } else { return mid; } } return -1; } private static> int binarySearch(T[] x, int low, int high, T key) { if(low <= high) { int mid = low + ((high -low) >> 1); if(key.compareTo(x[mid])== 0) { return mid; } else if(key.compareTo(x[mid])< 0) { return binarySearch(x,low, mid - 1, key); } else { return binarySearch(x,mid + 1, high, key); } } return -1; }}Copy the code

Note: the above code gives two versions of the split search, a recursive implementation, a circular implementation. Note that (high+ low) / 2 should not be used when calculating the middle position, as addition may cause the integer to be out of bounds. Instead, use one of the following three methods: Low + (high-low) / 2 or low + (high-low) >> 1 or (low + high) >>> 1