💂 personal home page :Java program fish 🤟 the entire Java system of interview questions I will share, we can continue to pay attention to 💬 if the article is helpful to you, welcome to follow, like, favorites (one button three links) and subscribe to the column oh. 💅 have any question welcome private letter, see will reply in time!
1. What is the difference between JDK and JRE?
JDK: Short for Java Development Kit, the Java Development Kit provides the Java Development environment and runtime environment.
JRE: Short for Java Runtime Environment. It provides the required Environment for Running Java.
Specifically, the JDK actually contains the JRE, as well as the compiler javac that compiles Java source code, as well as many tools for debugging and analyzing Java programs. Simply put: if you need to run Java programs, just install the JRE, and if you need to write Java programs, install the JDK.
What is the difference between equals and ==?
1) the effect of == reading on the base type and reference type == is different, as shown below:
- Basic type: compares whether the values are the same;
- Reference type: Compares whether references are the same;
Code examples:
String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true
Copy the code
Since x and y refer to the same reference, == is also true, while the new String() method overwrites the memory space, so == is false, and equals always compares values, so it is true.
2) Equals reading
Equals is essentially equal to ==, except that String and Integer and others have overridden the equals method to make it a value comparison. Take a look at the code below.
First, equals compares an object with the same value by default, as follows:
class Cat {
public Cat(String name) {
this.name = name;
}
private String name;
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Cat c1 = new Cat("Wang");
Cat c2 = new Cat("Wang");
System.out.println(c1.equals(c2)); // false
Copy the code
The output is false to our surprise. Equals equals equals equals equals equals equals equals equals equals equals equals equals equals
public boolean equals(Object obj) {
return (this == obj);
}
Copy the code
Equals is essentially equal to ==.
Why do two strings with the same value return true? The code is as follows:
String s1 = new String("Wang Lao Wu");
String s2 = new String("Wang Lao Wu");
System.out.println(s1.equals(s2)); // true
Copy the code
Similarly, when we go to String equals, we find the answer as follows:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while(n-- ! =0) {
if(v1[i] ! = v2[i])return false;
i++;
}
return true; }}return false;
}
Copy the code
String overrides Object’s equals method, changing reference comparison to value comparison.
Summary: == is a value comparison for primitive types and a reference comparison for reference types; Equals by default is a reference comparison, but many classes have redone equals (String, Integer, etc.) as a value comparison, so in general equals compares whether or not values are equal.
If two objects have the same hashCode(), equals() must also be true, right?
HashCode () is the same for both objects and equals() is not necessarily true.
Code examples:
String str1 = "Call";
String str2 = "Important";
System.out.println(String.format("| str2 str1: % d: % d", str1.hashCode(),str2.hashCode()));
System.out.println(str1.equals(str2));
Copy the code
Results of execution:
Str1:1179395 | str2:1179395 falseCopy the code
HashCode () is the same as hashCode(), but equals() is false, because in a hash table hashCode() equals the hash values of two key-value pairs. However, the hash values are equal, which does not necessarily result in the key-value pairs being equal.
4. What are the features of object-oriented?
A: Object-oriented features mainly have the following aspects:
1) Encapsulation hides the state information of the object as much as possible inside the object and only keeps limited interfaces and methods to interact with the outside world, so as to avoid external damage to the internal properties of the object.
Access control characters are used in Java to protect access to classes, variables, methods, and constructors. Java supports four different access permissions.
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.
2) inheritance
Java creates hierarchical classes through inheritance, which can be understood as a process by which one object obtains properties from another. Class inheritance is single inheritance, that is, it is illegal for a subclass to have only one parent:
public class extends Animal.Mammal{}
Copy the code
But we can implement it with multiple inheritance interfaces, such as:
public class Apple extends Fruit implements Fruit1.Fruit2{}
Copy the code
The two most commonly used keywords in inheritance are extends (for base and abstract classes) and implements (for interfaces). Note: Subclasses have all the member variables of their parent class, but they do not have access to the private member variables of their parent class, which ensures encapsulation of the parent class.
Here’s how to implement inheritance using the extends keyword.
public class Animal {}public class Mammal extends Animal {}public class Reptile extends Animal {}public class Dog extends Mammal {}Copy the code
By using the extends keyword, a subclass can inherit all the methods and properties of its parent class, but cannot use private methods and properties. We can determine that one object is a classification of another by using the instanceof operator.
public class Dog extends Mammal {
public static void main(String args[]) {
Animal a = new Animal();
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceofAnimal); }}Copy the code
The results are as follows:
truetruetrue
Copy the code
Use of the Implements keyword In cases where a class inherits an interface, the extends keyword cannot be used.
public interface Animal {}public class Mammal implements Animal {}public class Dog extends Mammal {}Copy the code
You can use the Instanceof operator to check whether the Mammal and dog objects are instances of the Animal class.
interface Animal {}class Mammal implements Animal {}public class Dog extends Mammal {
public static void main(String args[]) {
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceofAnimal); }}Copy the code
The running results are as follows:
truetruetrue
Copy the code
3) polymorphism
Polymorphism is the ability to have many different manifestations or forms of the same behavior. So polymorphism is multiple manifestations of an object so if I go to a pet store and SAY, “Please give me a pet,” and the waiter gives me a cat or a dog or a lizard, we say “pet” and that object is polymorphic.
example
public interface Vegetarian {}public class Animal {}public class Deer extends Animal implements Vegetarian {}Copy the code
Because Deer has multiple inheritance, it is polymorphic. The only way to access an object is through reference variables (compile-time variables). A reference variable can have only one type. Once declared, the type of a reference variable cannot be changed. Referential variables can not only be reset to other objects, provided those objects are not declared final. You can also reference objects of the same type or compatible with it. It can be declared as a class type or an interface type.
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;
Copy the code
All the reference variables D, A, V, and O refer to the same Deer object in the heap.
Let’s look at this example:
public class Animal {
public String name = "The parent class name";
public void move(a) {
System.out.println("Move" the parent class);
}
public void content(a) {
System.out.println("The parent class content"); }}Copy the code
public class Bird extends Animal {
public String name = "Subclass name";
@Override
public void move(a) { // TODO Auto-generated method stub
System.out.println("Subclasses move");
}
public void content(a) {
System.out.println("Subclasses content"); }}Copy the code
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
System.out.println(a.name);
a.move();
a.content();
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
Animal b = new Bird(); // The upward transition is done automatically by the system
// compile time variables run time variables
System.out.println(b.name);
b.move();
b.content();
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
Bird c = newBird(); System.out.println(c.name); c.move(); c.content(); }}Copy the code
Running results:
Superclass name parent move the parent class content -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the superclass name subclasses move subclass content -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- a subclass name subclasses move subclasses contentCopy the code
Bird class inherits Animal and overwrites its methods. Because Animal B = new Bird(), the compile-time variable is not the same as the run-time variable, so polymorphism occurs. As you can see from the final run result, the name member variable of the parent class and the two methods overridden by the subclass are called. As mentioned above, subclasses can call all non-private methods and properties of their parent class. Because name is a String object, unlike methods, the object’s domain is not polymorphic. When referencing a variable to access its contained instance variable, the system always sees a variable defined by its compile-time type, not by its runtime type.
If we change the Animal member variable to private, will we call the Bird member variable name and print it out? That is, the system always accesses variables defined by compile-time types.
Override definition: subclasses rewrite the implementation of the parent class’s accessible methods! Neither the return value nor the parameter can be changed. Namely shell unchanged, core rewrite!
Is String the most basic data type?
Strings are not part of the base type. There are eight basic types: byte, Boolean, char, short, int, float, long, and double. Strings are objects.
6, 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; .
7, 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.
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:
- Primitive types: Boolean, char, byte, short, int, long, float, double
- Wrapper types: Boolean, Character, Byte, Short, Integer, Long, Float, Double
class AutoUnboxingTest {
public static void main(String[] args) {
Integer a = new Integer(3);
Integer b = 3; // Automatically box 3 into type Integer
int c = 3;
System.out.println(a == b); // false Two references do not refer to the same object
System.out.println(a == c); // true a is automatically unpacked into int types and then compared with 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=<size>} 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 { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue ! = null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) Assert IntegerCache. High >= 127; } 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. Instead, the Integer object in the constant pool is referenced directly, so f1f2 is true and f3F4 is false.
** Warning: ** The more seemingly simple interview questions, the more mystery, the need for the interviewer to have a considerable skill.
9. The difference between & and &&?
Similarities: ampersand and ampers& can both be used as logical and operators to represent logical and (and).
Difference:
(1) && has the short-circuit function, while & does not have the short-circuit function.
(2) The & operator is true only if both sides of the expression are true. When the first expression of the && operator is false, the result is false and the second expression is not evaluated.
(3) & can also be used as a bitwise operator. When the expression surrounding the & operator is not Boolean, & represents bitwise and operation. We usually use 0x0f to ampersand an integer to get the lowest four bits of the integer, for example, 0x31 & 0x0f results in 0x01.
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).
** 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, and why this number is a prime number, and why 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(a) {
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: There is no length() method for arrays in Java, only the length property. Array array.length returns the length of the array. The String String has a length() method, and str.length() returns the length of the String.
14. How do I get out of the current multiple nested loops in Java?
Plan 1: Use tags
public static void main(String[] args) {
System.out.println("Before the mark");
ok: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.println("i=" + i + ",j=" + j);
if (j == 5)
break ok;
}
}
System.out.println("After the mark");
}
Copy the code
The use of tags is not recommended because it can disrupt the order of code execution
Scheme 2: the result of the outer loop condition expression can be controlled by the inner loop body code
public static void main(String[] args) {
System.out.println("Before the mark");
boolean flag = true;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10 && flag; j++) {
System.out.println("i=" + i + ",j=" + j);
if (j == 5)
flag = false;
}
}
System.out.println("After the mark");
}
Copy the code
15. Can the constructor be overridden?
A: Overrides occur in subclasses and superclasses, with the same method names, argument lists, return values, access modifiers, and exceptions. First, constructors can’t be inherited, because every class name is different, and constructors have the same name as the class name, which is definitely not inherited. So, since constructors can’t be inherited, they can’t be overridden, but they can be overridden.
Can I inherit the String class?
A: The String class is final and cannot be inherited.
** Add-on: ** 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).
What classes are available for manipulating strings in Java? What’s the difference between them?
Classes that operate on strings are: String, StringBuffer, StringBuilder.
The difference between String and StringBuffer and StringBuilder is that String declares an immutable object. Each operation generates a new String and then points to a new String. StringBuffer and StringBuilder can operate on existing objects, so it’s best not to use strings if you’re constantly changing the contents of strings.
The big difference between StringBuffer and StringBuilder is that StringBuffer is thread-safe and StringBuilder is non-thread-safe, but StringBuilder performs better than StringBuffer, So StringBuilder is recommended for single-threaded environments and StringBuffer is recommended for multi-threaded environments.
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";
String s4 = "ming";
String s5 = "Program" + "ming"; String s6 = s3 + s4; System.out.println(s1 == s2); System.out.println(s1 == s5); System.out.println(s1 == s6); System.out.println(s1 == s6.intern()); System.out.println(s2 == s2.intern()); }}Copy the code
Supplement: To answer the above interview questions, you need to clear two points: 1. The String object’s intern method gets a reference to the corresponding version of the String object 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; 2. The essence of the String + operation is to create a StringBuilder for append, and then use toString to process the StringBuilder into a String. This can be seen by using the javap -c stringequaltest. class command to obtain the JVM bytecode instructions corresponding to the class file.
What is the difference between Overload and Override?
First of all, overloading and overwriting are two different methods applied to two different scenarios:
Their respective characteristics:
Overload: first is in a class or subclass that has the same method name, but the method parameters are different and the return value types can be the same or different.
(1) The method name must be the same
(2) The parameter list of the method must be different.
(3) Access modifiers and return value types can be the same or different.
In simple terms: overloading is simply writing different methods for different situations. For example, in the same class, write different constructors to initialize different parameters.
Here is the code to demonstrate the reloading:
public class Animal {
public void bark(a){
System.out.println("animal can bark");
}
public void bark(String s){
System.out.println("animal"+ s +"can bark");
}
public void bark(int i){
System.out.println("The animal number "+i+" can bark");
}
public static void main(String[] args) {
Animal animal=new Animal();
animal.bark(1); }}Copy the code
Override: Generally refers to the relationship between a subclass and its parent class. Its main characteristics are: the method names and parameters are the same, but the specific implementation is different.
Features of rewriting:
(1) The method name must be the same and the return value type must be the same
(2) The parameter list must be the same
(3) The access cannot be lower than that of the overridden method in the parent class. For example, if a method of a parent class is declared public, overriding that method in a subclass cannot declare it protected.
(4) If a subclass and its parent are in the same package, the subclass can override all methods of the parent class except those declared private and final.
(5) The constructor cannot be overridden.
Simply put: it is the specific implementation class for the parent class of the method implementation is not satisfied, need to write a method to meet their own requirements.
public class Animal {
public void bark(a) {
System.out.println("animal can bark"); }}Copy the code
public class Dog extends Animal {
public void bark(a) {
System.out.println("Dog can bark");
}
public static void main(String[] args) {
Dog dog = newDog(); dog.bark(); }}Copy the code
Override: a subclass is not satisfied with the implementation of the corresponding method of its parent class and needs to implement its own requirements.
Describe how the JVM loads class files.
All classes in Java need to be loaded into the JVM by the class loader to run. The class loader is itself a class, and its job is to read the class file from the hard disk into memory. When writing programs, we hardly need to care about class loading because it is implicitly loaded, unless we have special uses, such as reflection, that require explicit loading of the required class.
There are two kinds of class loading methods: 1. Implicit loading, when the program encounters the object generated through new and other methods during the running process, the class loader is implicitly called to load the corresponding class into the JVM. 2. Explicit loading, using methods such as class.forname() to explicitly load the required classes
Java classes are loaded dynamically. Instead of loading all classes at once and then running them, the underlying classes (like the base classes) that the program runs on are fully loaded into the JVM, and other classes are loaded as needed. This, of course, is to save memory overhead.
There are three Java class loaders, corresponding to the three types of Java:
- Bootstrap Loader: starts a class Loader that is part of the VM. Responsible for loading the class libraries in the \lib directory into the virtual machine. It cannot be referenced directly by Java programs. Responsible for loading System classes (i.e., built-in classes like String, which correspond to the System class in C# and the C/C++ standard library classes)
- ExtClassLoader: responsible for loading extension classes (i.e., inheriting classes and implementing classes)
- AppClassLoader: is responsible for loading libraries specified on the user’s ClassPath (programmer custom classes).
The loading of classes in the JVM is implemented 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 runtime.
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 includes
- Verification: To ensure that the byte stream in the Class file meets the requirements of the current VM and does not compromise the vm’s own security.
- Preparation: Allocates memory for static variables and sets default initial values.
- Parse: Replace symbolic references with direct references.
Finally, the JVM initializes the class, including:
- If a class has a direct parent that has not already been initialized, initialize the parent first.
- If there are initialization statements in the class, they are executed in turn.
The loading of classes is accomplished by class loaders, including BootStrap, Extension, and Application.
Since Java 2 (JDK 1.2), the parent-delegate model (PDM) has been adopted for class loading. PDM ensures the security of the Java platform. In this mechanism, the JVM’s Bootstrap starts the class 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.
Parent delegate model: Requires that all loaders have their own parent class loaders except for the top-level start class loaders. The parent-child relationship between class loaders is generally not implemented as an inherited relationship, but by combining the code of the parent loader.
How it works: If a classloader receives a classload request, it does not try to load the class itself, but delegates the request to the parent classloader.
This is true at each level of class loaders, so all load requests should ultimately go to the top level of the boot class loader,
The child loader attempts to load itself only when the parent loader reports that it cannot complete the load request (its search scope did not find the required class).
Why you should Use it: Java classes have a hierarchical relationship with priority along with their classloaders.
For example, java.lang.object, which is stored in rt.jar, is delegated to the starting class loader by whichever class loader loads the class.
Therefore, the Object class is the same class in each classloader environment of the program.
A Java class with the same name as an existing class in the Rt.jar library can be compiled normally, but cannot be loaded and run.
The delegate mechanism prevents multiple copies of the same bytecode in memory, such as two classes A and B both loading the System class:
If you load your own without A delegate, class A loads A copy of System bytecode, and class B loads A copy of System bytecode, so there are two copies of System bytecode in memory. If the delegation mechanism is used, the parent class will be recursively searched. In other words, Bootstrap is the preferred method for trying to load the parent class. If the parent class cannot be found, the parent class will be recursively searched. In this case, the System can be found in the Bootstrap file and loaded. If the class B also needs to load the System file, the Bootstrap file will start from the Bootstrap file. If the Bootstrap file finds that the System file has already been loaded, the System file can be directly returned to the memory without reloading. There is only one copy of System bytecode in memory.
Can you write your own class called java.lang.system? Answer: Usually not, but alternative approaches can be taken to meet this need. In order to prevent us from writing the System class, class loading uses a delegate mechanism, which ensures that the parent class loader takes precedence. If the parent class loader can find the class, the child loader has no chance to load it. However, the System class is loaded by the Bootstrap loader. Even if I rewrite it myself, I always use the System provided by the Java System. The System class written by myself has no chance to be loaded at all.
However, we can do this by defining a class loader of our own, which must also be special in order to avoid the parent delegate mechanism. Since the system’s three classloaders all load classes in a specific directory, if our own classloader is placed in a specific directory, the system’s loader will not be able to load, which is ultimately loaded by our own loader.
20. Can a char variable store a Chinese character? Why?
- The char variable is used to store Unicode encoded characters, which include Chinese characters,
- So, of course, a char variable can store Chinese characters. However, if a particular character is not included in the
- Unicode encoded character sets, then, cannot store the special Chinese character in the char variable. supplement
- Note: Unicode encoding takes up two bytes, so variables of type CHAR also take up two bytes.
- Note: although the latter part of the answer is not in front of the question, but, in order to show their own knowledge and performance
- Thorough understanding of the problem, yes
- Answer some relevant knowledge and be sure to say everything you know.
public class Test8 {
public static void main(String[] args) {
char ch = 'in';
System.out.println("char:" + ch);
int max = Character.MAX_VALUE;
int min = Character.MIN_VALUE;
System.out.println(min + "<char<" + max);// 0<char<65535}}Copy the code
Char represents the range from 0 to 65535
21. What are the similarities and differences between abstract classes and interfaces?
Difference:
- The interface has only method definition, there is no concrete implementation, the implementation of the interface class to implement all methods of the interface; Abstract classes can have definitions and implementations;
- Interfaces and classes are implementation relationships, and classes can be multiple implementations; Abstract classes are inherited from classes and can only be inherited by one class.
- An abstract class can have an abstract method or no abstract method
- Interfaces don’t have static methods; abstract classes do.
- Constructors cannot be defined in interfaces, they can be defined in abstract classes.
Similarities:
- Can’t be instantiated
- You can use abstract classes and interface types as reference types
- A class that implements interfaces or inherits abstract classes must implement all abstract methods, otherwise it remains abstract.
22. What are the differences between ordinary classes and abstract classes?
- Ordinary classes cannot contain abstract methods. Abstract classes can contain abstract methods.
- Abstract classes cannot be instantiated directly; ordinary classes can be instantiated directly.
23. Must abstract classes have abstract methods?
No, abstract classes don’t have to have abstract methods.
Sample code:
abstract class Cat {
public static void sayHi(a) {
System.out.println("hi~"); }}Copy the code
In the code above, the abstract class does not have abstract methods but works perfectly fine.
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 Poker {
private static String[] suites = {"Spade"."Red peach"."Sucks"."Square"};
private static int[] faces = {1.2.3.4.5.6.7.8.9.10.11.12.13};
private Card[] cards;
/** * constructor ** /
public Poker(a) {
cards = new Card[52];
for(int i = 0; i < suites.length; i++) {
for(int j = 0; j < faces.length; j++) {
cards[i * 13 + j] = newCard(suites[i], faces[j]); }}}/** ** ** ** /
public void shuffle(a) {
for(int i = 0, len = cards.length; i < len; i++) {
int index = (int) (Math.random() * len); Card temp = cards[index]; cards[index] = cards[i]; cards[i] = temp; }}/** ** license *@paramIndex Licensing position * */
public Card deal(int index) {
return cards[index];
}
/** * Card class (a card) * [inner class] ** /
public class Card {
private String suite; / / design and color
private int face; / / points
public Card(String suite, int face) {
this.suite = suite;
this.face = face;
}
@Override
public String toString(a) {
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);
}
returnsuite + faceStr; }}}Copy the code
Test code:
class PokerTest {
public static void main(String[] args) {
Poker poker = new Poker();
poker.shuffle(); / / shuffle
Poker.Card c1 = poker.deal(0); // Deal the first card
// For the non-static inner class Card
// The Card object can only be created from its external class Poker object
Poker.Card c2 = poker.new Card("Red heart".1); // Create your own card
System.out.println(c1); // The first card after shuffling
System.out.println(c2); // Print: A of hearts}}Copy the code
Interview question – Where in the following code do compilation errors occur?
class Outer {
class Inner {}
public static void foo(a) { new Inner(); }
public void bar(a) { new Inner(); }
public static void main(String[] args) {
newInner(); }}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 memory leak is when objects or variables that are no longer in use remain in memory. In theory, Java has a GC garbage collection mechanism, which means that objects that are no longer in use are automatically reclaimed by the GC and erased from memory.
However, even then, Java still suffers from memory leaks, such as long-lived objects that hold references to short-lived objects.
Despite the short life cycle of the object is no longer needed, but because of long life cycle object holds its reference that can’t be recycled, which is memory leaks in Java takes place, in layman’s terms, is the programmer may create an object that has no longer use this object, the object has been quoted, That this object is useless but not reclaimed by the garbage collector, this is the situation possible memory leaks in Java, for example, caching system, we have loaded an object in the cache (in a global map object, for example), and no longer use it, the object has been cached reference, but no longer be used.
To check for memory leaks in Java, make sure that the program executes all branches to the end of the program, and then see if an object is used. If not, the object is a memory leak.
If an external object instance of a class of the method returns an inner class instance of the object, the inner class object was cited for a long time, even if the external class instance objects no longer be used, but as a result of the inner class lasting external instance objects of a class, the external class object will not be garbage collected, this will cause memory leaks.
(2) When an object is stored in a HashSet, it cannot modify the fields in the object that computed the hash value. Otherwise, the modified hash value of the object will be different from the original hash value stored in the HashSet. In this case, the hash value of the object will be different from the original hash value. Even if the Contains method retrieves an object from the HashSet collection using the current reference to the object as an argument, it returns a result that the object is not found, which makes it impossible to remove the current object from the HashSet collection separately, causing a memory leak.
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. The difference between static and instance variables.
In Java, static variables and instance variables can be collectively referred to as member variables. First, understand what static variables are, what instance variables are, and the form they define. Static variables, also called class variables, are independent of methods and have the static modifier. Instance variables are also independent variables that are independent of methods, but without the static modifier.
Here’s an example:
public class StaticTest {
private static int staticInt = 2;// Static variables
private int random = 2;// Instance variables
public StaticTest(a) {
staticInt++;
random++;
System.out.println("staticInt = "+staticInt+" random = "+random);
}
public static void main(String[] args) {
StaticTest test = new StaticTest();
StaticTest test2 = newStaticTest(); }}Copy the code
Seeing the code above, you can think about the test results.
Here are the correct answers:
staticInt = 3 random = 3
staticInt = 4 random = 3
Copy the code
Is it what you think it is? The above example illustrates the difference between a static variable and an instance variable.
Here’s the dry stuff. Take care of it.
The differences are summarized as follows:
An instance variable is a property of an object that must be created before the instance variable is allocated space. Combine the examples given above. Every time an instance object is created, a Random is allocated. The random values between instance objects do not affect each other, so this explains why the two output random values are the same.
Static variables do not belong to an instance object, but to the entire class. As soon as the program loads the class’s bytecode without creating any instance objects, the static variable is allocated space and can be used. With the example given above, no matter how many instance objects are created, only one staticInt variable is always assigned, and the staticInt is incrementing with each instance object created.
In general, an instance variable must be created before it can be used with that object; Static variables, on the other hand, can be referenced directly by the class name (or by the instance object if it exists).
In fact, this also explains why static methods don’t have to be called after the instance object is created. Methods that are not static must be associated with an object, and an object must be created before a method call can be made on that object.
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;
import java.io.Serializable;
public class MyUtil {
private MyUtil(a) {
throw new AssertionError();
}
@SuppressWarnings("unchecked")
public static <T extends Serializable> 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();
// Note: It makes no sense to call the close method of ByteArrayInputStream or ByteArrayOutputStream
// These two memory-based streams can free resources as soon as the garbage collector cleans up the object, unlike external resources such as file streams}}Copy the code
Here is the test code:
/** ** human ** /
class Person implements Serializable {
private static final long serialVersionUID = -9102017020286042305L;
private String name; / / name
private int age; / / age
private Car car; / /
public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge(a) {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar(a) {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString(a) {
return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; }}Copy the code
/** ** ** /
class Car implements Serializable {
private static final long serialVersionUID = -5713945027627603702L;
private String brand; / / brand
private int maxSpeed; // Maximum speed
public Car(String brand, int maxSpeed) {
this.brand = brand;
this.maxSpeed = maxSpeed;
}
public String getBrand(a) {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getMaxSpeed(a) {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
@Override
public String toString(a) {
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); // Deep clone
p2.getCar().setBrand("BYD");
// Modify the brand attributes of the car object associated with Person object P2
// The car associated with the original Person object P1 will not be affected
// Because when the Person object is cloned, its associated car object is also cloned
System.out.println(p1);
} catch(Exception e) { e.printStackTrace(); }}}Copy the code
Note: * * * * is 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’s always better to expose problems at compile time than to leave them to 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.
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 approach divides the heap memory into different regions depending on the life cycle of Java objects, and objects may be moved to different regions during garbage collection:
- Eden: This is the area where the object was born, and for most objects, this is the only area 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(a) {
System.out.print("2"); }}class B extends A{
static {
System.out.print("a");
}
public B(a) {
System.out.print("b"); }}public class Hello {
public static void main(String[] args) {
A ab = new B();
ab = newB(); }}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.
** If you cannot give the correct answer to this question, you have not understood the Java class loading mechanism completely.
Conversion between data types:
– How to convert strings to primitive data types? – 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 reverse a string?
A: Use the Reverse () method of StringBuilder or stringBuffer.
Sample code:
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("abcdefg");
System.out.println(stringBuffer.reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("abcdefg");
System.out.println(stringBuilder.reverse()); // gfedcba
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 the 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)); / / 0-11
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()); / / 1-12System.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(); // Java 8
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
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.
Here is a comparison of the similarities and differences between the two languages:
- Object based and Object oriented: Java is a true object oriented language, even to develop simple programs, 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. (Today’s browsers almost all use just-in-time (JIT) technology to make JavaScript more efficient.)
- 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.
- The code format is different.
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 <= 0
Copy 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: First of all, exceptions and errors are derived from the Throwable class. In Java, only instances of Throwable can be thrown or caught.
Exception and Error represent two ways in which the JAVA language handles exceptions.
An Exception is an Exception that can be expected when a Java program is running. We can get such an Exception and handle it out of business.
An Error is an unexpected exception that occurs during the execution of a Java program. When such an exception occurs, the JVM cannot handle or recover from it. This makes it impossible to catch exceptions like OutOfMemoryError, NoClassDefFoundError, and so on.
Exceptions are classified into checking exceptions and non-checking exceptions. The two fundamental differences are that checking exceptions must be caught using a try catch (e.g., IOException) when you write code. Non check exception In writing code, you can ignore capture operations (such as: ArrayIndexOutOfBoundsException), the exception is in the process of writing code or use through the specification can be avoided.
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 a finally block exists, 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 completes. 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 recoverable cases and run time exceptions for programming errors
- Avoid unnecessary use of checked exceptions (exceptions can be avoided by means of state detection)
- Standard exceptions are preferred
- Every exception thrown by a method should be documented
- Maintain the atomicity of the anomaly
- Do not ignore caught exceptions in a catch
49, List some of your common runtime exceptions.
A:
- Java. Lang. NullPointerException, this explanation is that the program had a null pointer, in brief is invoked the uninitialized object or there is no such thing as objects, this error often occurs in creating images, called an array of these operations, such as uninitialized images, Or the wrong path when creating the image and so on.
- Java. Lang. ClassNotFoundException, abnormal explanation is “the specified class does not exist,” here is mainly consider the name of the class and the path is correct
- Java. Lang. ArrayIndexOutOfBoundsException, “array subscript crossing the line” is the explanation of this exception, are now mostly in the program to the operation of the array, so the array when the call must be carefully check, see his calls the subscript is beyond the scope of the array, in general, Explicit (that is, direct subscripts with constants) calls are less prone to such errors, but implicit (that is, subscripts with variables) calls are often wrong.
- Java. Lang. NoSuchMethodError, the method does not exist error. This error is thrown when an application tries to call a method of a class that does not have a definition for the method.
- Java. Lang. IndexOutOfBoundsException, index cross-border anomalies. This exception is thrown when the index value accessing a sequence is less than 0 or greater than or equal to the size of the sequence.
- Java. Lang. A NumberFormatException, abnormal number format. This exception is thrown when an attempt is made to convert a String to the specified numeric type, but the String does not conform to the format required by the numeric type.
- Java.sql. SQLException, SQL statement execution exception
- Java.io.IOException, input/output exception
- Java. Lang. IllegalArgumentException, method parameter error
- Java. Lang. IllegalAccessException, no abnormal access permissions
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, 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 objects 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 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");
throwa; }}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).
* * added: Properties is a special key-value pair mapping where both keys and values are 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<Student> {
private String name; / / name
private int age; / / age
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString(a) {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
return this.age - o.age; // Compare ages (ascending order of ages)}}Copy the code
import java.util.Set;
import java.util.TreeSet;
class Test01 {
public static void main(String[] args) {
Set<Student> set = new TreeSet<>(); // Java 7 diamond syntax (no need to write type in Angle brackets after constructor)
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);
}
// Output result:
// Student [name=Bob YANG, age=22]
// Student [name=XJ WANG, age=32]
// Student [name=Hao LUO, age=33]
// Student [name=Bruce LEE, age=60]}}Copy the code
Example 2:
public class Student {
private String name; / / name
private int age; / / age
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/** * get student name */
public String getName(a) {
return name;
}
/** * get the student age */
public int getAge(a) {
return age;
}
@Override
public String toString(a) {
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<Student> list = new ArrayList<>(); // Java 7 diamond syntax (no need to write type in Angle brackets after constructor)
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));
// Pass in a Comparator interface object as the second argument to the sort method
// This is equivalent to passing an algorithm to sort to compare object sizes
// Since Java has no such concepts as function Pointers, parsers, and delegates
// So the only option to pass an algorithm into a method is through an interface callback
Collections.sort(list, new Comparator<Student> () {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName()); // Compare student names}});for(Student stu : list) {
System.out.println(stu);
}
// Output result:
// Student [name=Bob YANG, age=22]
// Student [name=Bruce LEE, age=60]
// Student [name=Hao LUO, age=33]
// Student [name=XJ WANG, age=32]}}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.
** Some 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.
A:
- Wait () : to cause a thread to wait(block) and release the lock on its holding object;
- Sleep () : puts a running thread to sleep and 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. This method does not lock the object to all threads, but makes them compete. Only the thread that acquired the lock can enter the ready state.
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.
- Bank Account:
/** * bank account ** /
public class Account {
private double balance; // Account balance
/** * deposit *@paramMoney Deposit amount */
public void deposit(double money) {
double newBalance = balance + money;
try {
Thread.sleep(10); // It takes some processing time to simulate this business
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
balance = newBalance;
}
/** * get the account balance */
public double getBalance(a) {
returnbalance; }}Copy the code
- Saving thread class:
/** * save thread ** /
public class AddMoneyThread implements Runnable {
private Account account; // Deposit into account
private double money; // Deposit amount
public AddMoneyThread(Account account, double money) {
this.account = account;
this.money = money;
}
@Override
public void run(a) { account.deposit(money); }}Copy the code
- The test class:
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
/** * bank account ** /
public class Account {
private double balance; // Account balance
/** * deposit *@paramMoney Deposit amount */
public synchronized void deposit(double money) {
double newBalance = balance + money;
try {
Thread.sleep(10); // It takes some processing time to simulate this business
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
balance = newBalance;
}
/** * get the account balance */
public double getBalance(a) {
returnbalance; }}Copy the code
- Synchronizing bank accounts when the thread calls the deposit method
/** * save thread ** /
public class AddMoneyThread implements Runnable {
private Account account; // Deposit into account
private double money; // Deposit amount
public AddMoneyThread(Account account, double money) {
this.account = account;
this.money = money;
}
@Override
public void run(a) {
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;
/** ** bank account ** */
public class Account {
private Lock accountLock = new ReentrantLock();
private double balance; // Account balance
/** * deposit **@paramMoney * Deposit amount */
public void deposit(double money) {
accountLock.lock();
try {
double newBalance = balance + money;
try {
Thread.sleep(10); // It takes some processing time to simulate this business
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
balance = newBalance;
}
finally{ accountLock.unlock(); }}/** * get the account balance */
public double getBalance(a) {
returnbalance; }}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<Integer> {
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<Future<Integer>> 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<Integer> future : list) {
// while(!future.isDone()) ;
sum += future.get();
}
System.out.println(sum);
}
}
Copy the code
62, Synchronized?
Synchronized keyword can be used in the following three ways:
- Modifier instance method, used to lock the current instance, before entering the synchronization code to obtain the current instance lock
- Modifies a static method that locks the current class object before entering the synchronized code
- Modifies a block of code that specifies a lock object, locks a given object, and acquires the lock for the given object before entering a synchronized code base.
Synchronized is used to modify the instance method of an instance object. Note that the instance method does not include static methods, as follows:
public class AccountingSync implements Runnable {
// Share resources (critical resources)
static int i = 0;
/** * synchronized modifs instance methods */
public synchronized void increase(a) {
i++;
}
@Override
public void run(a) {
for (int j = 0; j < 1000000; j++) { increase(); }}public static void main(String[] args) throws InterruptedException {
AccountingSync instance = new AccountingSync();
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
/** * Output result: 2000000 */
}
Copy the code
In the above code, we have two threads operating on the same shared resource, variable I, since I ++; Does not have the atomic operation, the operation is to read the values first, then write back to a new value, equivalent to the original value plus 1, done in two steps, if the second thread to read the old values and write back to the first thread reads the I during the period of the new value domain values, then the second thread will see the same value with the first thread, and perform the same value plus one operation, This is a thread-safe failure, so you must use the synchronized modifier for the increase method to keep thread-safe. Note that synchronized modifiers the instance method increase, in which case the lock on the current thread is the instance object. In Java, thread-synchronization locks can be any object. This is indeed true from the code execution results; if we hadn’t used the synchronized keyword, the final output would probably have been less than 2,000,000, which is where the synchronized keyword comes in. Here we also need to realize that when one thread is accessing an object’s synchronized instance method, other threads cannot access the object’s other synchronized methods. After all, an object has only one lock, and when one thread acquires the lock, other threads cannot acquire the lock. So the object’s other synchronized instance methods cannot be accessed, but other threads can still access the object’s other non-synchronized methods. Of course, if thread A needs to access the synchronized method f1 of obj1 (the current lock is obj1), and thread B needs to access the synchronized method f2 of obj2 (the current lock is obj2), This is allowed because the two instance locks are not identical. If two threads are operating on data that is not shared, thread-safety is guaranteed. Unfortunately, if two threads are operating on data that is shared, thread-safety may not be guaranteed.
public class AccountingSyncBad implements Runnable{
static int i=0;
public synchronized void increase(a){
i++;
}
@Override
public void run(a) {
for(int j=0; j<1000000;j++){
increase();
}
}
public static void main(String[] args) throws InterruptedException {
/ / new new instances
Thread t1=new Thread(new AccountingSyncBad());
/ / new new instances
Thread t2=new Thread(new AccountingSyncBad());
t1.start();
t2.start();
Thread A waits for thread A to terminate before returning from thread.join()t1.join(); t2.join(); System.out.println(i); }}Copy the code
The difference is that we create two new instances AccountingSyncBad at the same time, and then start two different threads to operate on the shared variable I. Unfortunately, the result is 1452317 instead of 2000000, because the code made a serious error. Although we modify the increase method with synchronized, two different instance objects are new, which means that there are two different instance object locks, so T1 and T2 enter their own object locks, which means that t1 and T2 threads use different locks, so thread safety cannot be guaranteed. The solution to this dilemma is to use synchronized on a static increase method, in which case the object lock is unique to the current class object, since no matter how many instance objects are created, there is only one for the class object. Let’s take a look at using a static increase method that applies synchronized.
Synchronized when synchronized is used on a static method, the lock is the class object lock of the current class. Because static members are not exclusive to any instance object and are class members, concurrent operations on static members can be controlled through class object locks. Note that if thread A calls the non-static synchronized method of an instance object and thread B calls the static synchronized method of the class that the instance object belongs to, the mutual exclusion will not occur. The lock used to access a static synchronized method is the current class object, and the lock used to access a non-static synchronized method is the current instance object lock.
public class AccountingSyncClass implements Runnable{
static int i=0;
/** * on static methods, the lock is on the current class object, that is, the corresponding class object */ of the * AccountingSyncClass class
public static synchronized void increase(a){
i++;
}
/** * non-static, access to different locks will not be mutually exclusive */
public synchronized void increase4Obj(a){
i++;
}
@Override
public void run(a) {
for(int j=0; j<1000000;j++){
increase();
}
}
public static void main(String[] args) throws InterruptedException {
/ / new new instances
Thread t1=new Thread(new AccountingSyncClass());
/ / the new heart
Thread t2=new Thread(new AccountingSyncClass());
// Start the threadt1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}Copy the code
Because the synchronized keyword modifies static increase methods, its lock object is the class object of the current class, unlike the synchronized method that modifies instance methods. Note that the increase4Obj method in this code is an instance method whose object lock is the current instance object. If it is called by another thread, there will be no mutual exclusion (lock objects are different, after all), but we should be aware that thread-safety issues can be found in this case (handling the shared static variable I).
(3) the synchronized synchronized code block In addition to using keywords to modify instance method and static method, you can also use the synchronized code block, in some cases, we can write the method body is bigger, at the same time there are some more time-consuming operation, and need to be synchronized code and only a small part, if the synchronous operation on the whole method for directly, In this case, we can use synchronized code blocks to wrap the code that needs to be synchronized, so that there is no need to synchronize the whole method. An example of synchronized code blocks is as follows:
public class AccountingSync implements Runnable{
static AccountingSync instance=new AccountingSync();
static int i=0;
@Override
public void run(a) {
// Omit other time-consuming operations....
// use the synchronization block to synchronize variable I with the lock object instance
synchronized(instance){
for(int j=0; j<1000000; j++){ i++; }}}public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(instance);
Thread t2=newThread(instance); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}Copy the code
It can be seen from the code that synchronized is applied to a given instance object, that is, the current instance object is the lock object. Each time a thread enters the code block wrapped by synchronized, the current thread is required to hold the instance object lock. If other threads currently hold the lock, New threads must wait, ensuring that only one thread executes i++ at a time; Operation. In addition to instance as an object, we can also use this object (representing the current instance) or the current class object as the lock, as follows:
//this, the current instance object lock
synchronized(this) {for(int j=0; j<1000000;j++){
i++;
}
}
/ / class object lock
synchronized(AccountingSync.class){
for(int j=0; j<1000000;j++){
i++;
}
}
Copy the code
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 the pooling of resources technique 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. * If the thread pool configuration is complete and the mechanism of the thread pool is not clear, so the following static factory methods are provided for the tool Executors:
- NewSingleThreadExecutor: Creates 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 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: Create 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:
* * note: ** Running indicates the Running state, Runnable indicates the ready state, and Blocked indicates the Blocked state. The Blocked state can be caused by calling the wait() method to enter the wait pool, or by executing a synchronous 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(a) {
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: the Java 7 TWR used 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 {
// The methods in the utility class are accessed statically so making the constructor private does not allow object creation (absolutely good practice)
private MyUtil(a) {
throw new AssertionError();
}
/** * Count occurrences of a given string in a given file **@paramFilename filename *@paramWord string *@returnNumber of occurrences of a string in a 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();
}
returncounter; }}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<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
System.out.println(file.getFileName().toString());
returnFileVisitResult.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(newClientHandler(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(a) {
try(BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter pw = new PrintWriter(client.getOutputStream())) {
String msg = br.readLine();
System.out.println("Receive" + client.getInetAddress() + "发送的: " + 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 indirectly implement the AutoCloseable interface (single-method callback interface), it is possible to use THE TWR syntax to automatically call the close() method of the external resource class 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:");
String msg = sc.nextLine();
sc.close();
PrintWriter pw = new PrintWriter(client.getOutputStream());
pw.println(msg);
pw.flush();
BufferedReader br = new BufferedReader(newInputStreamReader(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; // Multiplexing selector
private static ByteBuffer buffer = null; / / the buffer
public static void main(String[] args) {
init();
listen();
}
private static void init(a) {
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 newRuntimeException(e); }}private static void listen(a) {
while (true) {
try {
if(selector.select(ECHO_SERVER_TIMEOUT) ! =0) {
Iterator<SelectionKey> 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("Receive" + channel.getRemoteAddress() + "The news:" + 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(a) {}public static ByteBuffer encode(CharBuffer in) throws CharacterCodingException{
return encoder.encode(in);
}
public static CharBuffer decode(ByteBuffer in) throws CharacterCodingException{
returndecoder.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: How XML documents are defined: There are two forms of definition, DTD document type definition and Schema schema. Essential differences: Schemas themselves are XML and can be parsed by XML parsers (which is the fundamental purpose of developing schemas from DTDS). Common differences:
- Schema is an open content model, extensible and functional, while DTD has poor scalability.
- Shema supports rich data types, while DTDS do not support element data types and have limited type definitions for attributes.
- Schema supports the namespace mechanism, while DTD does not.
- Schema can validate entire XML documents or parts of documents for different situations; DTD lacks this flexibility.
- Schema completely follows XML specification, conforms to XML syntax, can be combined with DOM, powerful; DTD syntax has its own syntax and requirements that can be difficult to learn.
Parsing XML documents:
- DOM parsing: THE full name of DOM is Document Object Model, also known as Document Object Model. In an application, a DOM-based XML parser transforms an XML document into a collection of object models (usually called DOM trees), and it is through this object model that applications operate on XML document data. The DOM interface allows an application to access any part of the DATA in an XML document at any time, so this mechanism is also known as random access.
- SAX parsing: SAX stands for Simple APIs for XML. Unlike DOM, SAX provides a sequential access pattern, which is a quick way to read and write XML data. When using SAX analyzer to analyze XML documents, a series of events will be triggered and the corresponding event handler functions will be activated. The application program realizes the access to XML documents through these event handler functions, so SAX interface is also called event-driven interface.
- JDOM parsing: JDOM uses the Collection architecture in Java to encapsulate collections, a pattern more familiar to Java enthusiasts
- DOM4J parsing: The XML parser loads the entire XML Document into memory at one time, and then builds a Document object tree in memory. Through the Document object, the node object in the tree is obtained, and the content of the XML Document is accessed (manipulated) through the node object
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.
** Sidebars: ** Now that fashionable software such as Sublime has started to write configuration files as JSON, we have a strong sense that another feature of XML is on the way out of 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.
- Load the driver.
Class.forName("oracle.jdbc.driver.OracleDriver");
Copy the code
- Create a connection.
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl"."scott"."tiger");
Copy the code
- Create statement.
PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?");
ps.setInt(1.1000);
ps.setInt(2.3000);
Copy the code
- Execute the statement.
ResultSet rs = ps.executeQuery();
Copy the code
- Processing results.
while(rs.next()) {
System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"));
}
Copy the code
- Close the resource.
finally {
if(con ! =null) {
try {
con.close();
} catch(SQLException e) { e.printStackTrace(); }}}Copy the code
** External resources should be closed in the reverse order in which they are opened, i.e., close a ResultSet first, then a Statement, 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?
Relationships and differences between a Statement and a PreparedStatement. Preparedstatements can use placeholders, are precompiled, and are more efficient than preparedStatements in batch processing
A:
(1) PreparedStatement: an object that represents a pre-compiled SQL statement. SQL statements are precompiled and stored in a PreparedStatement object. You can then use this object to efficiently execute the statement multiple times. Note: The setting methods used to set the value of the IN parameter (setShort, setString, and so on) must specify a type compatible with the defined SQL type of the input parameter. For example, if the IN parameter has an SQL type INTEGER, then the setInt method should be used, and the position of the question mark should also be noted, because the first greeting position is 1 and the second question mark position is 2. And so on.
If arbitrary parameter type conversions are required, the setObject method should be used with the target SQL type as its argument. In the following example of setting parameters, con represents an active connection:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1.1533.00)
pstmt.setInt(2.1102)
pstmt.execute()// Note that there can be no MORE SQL statements in the commit, unlike Statment
Copy the code
Demo code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class PreparedStatementTest {
public static void main(String[] args) {
test_autoCommit();
}
public static void test_autoCommit(a) {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "JDBC: oracle: thin: @ 127.0.0.1:1521: wouldn";
String user = "admin";
String password = "admin";
Connection conn = null;
PreparedStatement ps = null;
try {
// 1. Register driver
Class.forName(driver);
// get the connection
conn = DriverManager.getConnection(url, user, password);
// System.out.println(conn);
// 3. Create a prepareStatement object
String sql = "insert into lover values(? ,? ,?) ";
ps = conn.prepareStatement(sql);
// execute the SQL statement
ps.setInt(1.21);// set to the first? The value of the sign position is 21 of type Int
ps.setString(2."suwu150");// set to the second? The value of the symbol position is String suwu150
java.util.Date utilDate = new java.util.Date();// Convert date from util to SQL
ps.setDate(3.new java.sql.Date(utilDate.getTime()));
// ps.execute(); / / execution
System.out.println(ps.execute());// Execute the table to print the result returned, which is false because there is no result set returned
// 5
} catch (Exception e) {
e.printStackTrace();
} finally {
// close the resource
try {
if(ps ! =null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn ! =null)
conn.close();
} catch(SQLException e) { e.printStackTrace(); }}}}Copy the code
The result of the insertion
ID | NAME | BIRTHDAY |
---|---|---|
21 | suwu150 | 06 – October – 16 |
(2) Statement: An object used to execute a static SQL Statement and return the result it generates. By default, only one ResultSet object can be opened per Statement object at a time. Therefore, if reading a ResultSet object intersects with another, the two objects must have been generated by different Statement objects. If there is an open current ResultSet object for a Statement, it is implicitly closed by all execution methods in the Statement interface. Perform the following operations: Create a Statement object
Statement stat=conn.createStatement();
String sql="insert into lover values(6,'xiaohong',to_date('21-9-2016','dd-mm-yyyy'))";
stat.execute(sql);// The commit should have a SQL statement, as opposed to PreparedStatment
Copy the code
Take a look at it in action:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class StatementTest {
public static void main(String[] args) {
test_autoCommit();
}
public static void test_autoCommit(a) {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "JDBC: oracle: thin: @ 127.0.0.1:1521: wouldn";
String user = "admin";
String password = "admin";
Connection conn = null;
Statement stat = null;
try {
// 1. Register driver
Class.forName(driver);
// get the connection
conn = DriverManager.getConnection(url, user, password);
conn.setAutoCommit(false);
// System.out.println(conn);
// create a statement object
stat = conn.createStatement();
// execute the SQL statement
String sql = "insert into lover values(22,'xiaohong',to_date('21-9-2016','dd-mm-yyyy'))"; // Pay attention to the format
// stat.execute(sql);
System.out.println(stat.execute(sql)); // The return value is false because there is no ResultSet returned
conn.commit();
// 5
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch(SQLException e1) { e1.printStackTrace(); }}finally {
// close the resource
try {
if(stat ! =null)
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn ! =null)
conn.close();
} catch(SQLException e) { e.printStackTrace(); }}}}Copy the code
Result after insertion:
ID | NAME | BIRTHDAY |
---|---|---|
22 | xiaohong | – – 16 September 21 |
21 | suwu150 | 06 – October – 16 |
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.
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?
A:
- Atomic: all operations in a transaction can be done or not done. Failure of any operation will result in failure of the whole transaction.
- Consistent: The system state is Consistent after a transaction;
- Isolated: Concurrently executed transactions cannot see each other’s intermediate state;
- Durable: Changes made after a transaction is finished are persisted, even if a catastrophic failure occurs. Log and synchronous backups can be used to rebuild data after a failure.
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 {
// 1. Load the driver (Java6 or later can be omitted)
Class.forName("com.mysql.jdbc.Driver");
// 2. Establish a connection
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test"."root"."123456");
// 3. Create statement objects
PreparedStatement ps = con.prepareStatement("insert into tb_user values (default, ? ,?) ");
ps.setString(1."hzy"); // Replace the first placeholder in the SQL statement with a string
try (InputStream in = new FileInputStream("test.jpg")) { // Java 7的TWR
ps.setBinaryStream(2, in); // Replace the second placeholder in the SQL statement with a binary stream
// 4. Issue a SQL statement to obtain the number of affected rows
System.out.println(ps.executeUpdate() == 1 ? "Insert successful" : "Insert failed");
} catch(IOException e) {
System.out.println("Failed to read photo!"); }}catch (ClassNotFoundException | SQLException e) { // Java 7 multi-exception capture
e.printStackTrace();
} finally { // Code that releases external resources should be placed in finally to ensure that it can be executed
try {
if(con ! =null && !con.isClosed()) {
con.close(); // 5. Release database connection
con = null; // indicates that the garbage collector can reclaim the object}}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.
Note: * * * * computer was born in the early processing of information are almost all values, but times have changed, today we use computer processing information more often rather than numeric string, the regular expression is in string matching and processing is the most powerful tool for most language provides 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 = "Beijing (Chaoyang District)(Xicheng District)(Haidian District)";
Pattern p = Pattern.compile(". *? (? = \ \ ()");
Matcher m = p.matcher(str);
if(m.find()) { System.out.println(m.group()); }}}Copy the code
** The above regular expressions use lazy matching and look-forward, if you are not aware of these content, I recommend reading the popular online regular Expressions 30-minute Tutorial.
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: Call newInstance() through class objects, such as 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;
/** * Reflection tools ** /
public class ReflectionUtil {
private ReflectionUtil(a) {
throw new AssertionError();
}
/** * takes the value * of the specified field (property) of the object by reflection@paramTarget Target object *@paramThe name of the fieldName field *@throwsThrows an exception * if the value of the specified field of the object is not retrieved@returnThe value of the field */
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 newRuntimeException(e); }}/** * Assigns a value * to the specified field of the object by reflection@paramTarget Target object *@paramThe name of the fieldName field *@paramThe value value * /
public static void 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 newRuntimeException(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)); // HELLO}}Copy the code
89. Briefly describe the “six Principles and one Law” of object orientation
A:
- The 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: Programming to the interface. (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: 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.
- The principle of composite aggregation reuse: reuse code using aggregation or composite relationships 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. When asked about design patterns in an interview, you can choose the most common answers, such as:
- Factory pattern: Factory classes can generate instances of different subclasses based on conditions that have a common abstract parent and implement the same methods, but that perform different operations on different data (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 that 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 pattern: Transforms the interface of one class into another interface that the client expects so that classes that cannot be used together because of interface mismatches can work together.
- Template method pattern: Provide an abstract class that implements some of the logic as concrete methods or constructors, and then declare 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:
- Hangry singleton
public class Singleton {
private Singleton(a){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(a){
returninstance; }}Copy the code
- Lazy singleton
public class Singleton {
private static Singleton instance = null;
private Singleton(a) {}
public static synchronized Singleton getInstance(a){
if (instance == null) the instance =new Singleton();
returninstance; }}Copy the code
Make the constructor private and do not allow the outside world 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 pattern: encapsulating algorithms into separate classes with common interfaces so they can be interchanged) ** /
public interface Sorter {
/** * sort *@paramList Array to sort */
public <T extends Comparable<T>> void sort(T[] list);
/** * sort *@paramList Array * to be sorted@paramComp comparer */ that compares two objects
public <T> void sort(T[] list, Comparator<T> comp);
}
Copy the code
import java.util.Comparator;
/** * bubble sort ** */
public class BubbleSorter implements Sorter {
@Override
public <T extends Comparable<T>> 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 <T> void sort(T[] list, Comparator<T> 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 <T extends Comparable<T>> int binarySearch(T[] x, T key) {
return binarySearch(x, 0, x.length- 1, key);
}
// Binary search using a loop
public static <T> int binarySearch(T[] x, T key, Comparator<T> 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 {
returnmid; }}return -1;
}
// Binary search with recursive implementation
private static<T extends Comparable<T>> 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
** The code above 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