The following content is responsible questions and answers given after the original Java interview question set and answers were fully revised. There were many duplicate questions and valuable questions in the original questions, and many reference answers were also wrong. The modified Java interview question set references the latest version of JDK, removes useless content such as EJB 2.x, and supplements the data structure and algorithm-related questions, classic interview programming questions, large website technical architecture, operating system, database, software testing, design patterns, UML and other content. At the same time, many knowledge points were also analyzed in depth, such as the design of the hashCode method, the heap and generation of garbage collection, the new concurrent programming of Java, NIO.2, etc. I believe that it will be beneficial to Java programmers who are preparing to join.
Java programmer interview questions set (1-50)
1. Java basics
1. What are the aspects of object-oriented characteristics?
Answer: The main aspects of object-oriented features are:
1) Abstract: Abstraction is the process of summarizing the common characteristics of a type of object into a class of objects, including data abstraction and behavior abstraction. Abstraction only focuses on what attributes and behaviors the object has, and does not pay attention to what the details of these behaviors are.
2) Inheritance: Inheritance is the process of obtaining inheritance information from existing classes and creating new classes. The class that provides inherited information is called the parent class (superclass, base class); the class that obtains inherited information is called the subclass (derived class). Inheritance gives the changing software system a certain degree of continuity, and inheritance is also an important means of encapsulating variable factors in the program (if you cannot understand it, please read the part about bridge mode in Dr. Yan Hong's "Java and Patterns" or "Design Patterns Exquisites").
3) Encapsulation: It is generally believed that encapsulation is to bind data to the method of operating data, and access to data can only be achieved through the defined interface. The essence of object-oriented is to portray the real world as a series of completely autonomous and closed objects. The method we write in a class is to encapsulate implementation details; we write a class is to encapsulate data and data operations. It can be said that packaging is to hide everything that can be hidden, and only provides the simplest programming interface to the outside world (you can think about the difference between an ordinary washing machine and a fully automatic washing machine. It is obvious that the fully automatic washing machine is packaged better and therefore easier to operate; the smartphone we are using now is also packaged well enough because a few buttons can handle everything).
4) Polymorphism: Polymorphism refers to allowing objects of different subtypes to respond differently to the same message. Simply put, it is to call the same method with the same object reference but do different things. Polymorphisms are divided into compile-time polymorphisms and run-time polymorphisms. If the object's method is regarded as a service provided by the object to the outside world, then the runtime polymorphism can be explained as: when system A accesses the services provided by system B, system B has multiple ways to provide services, but everything is transparent to system A (just like an electric shaver is system A, its power supply system is system B, system B can be powered by batteries or AC, and it may even be solar energy. System A will only call the power supply method through class B objects, but it does not know what the underlying implementation of the power supply system is and how it obtains power). Method overloading implements compile-time polymorphism (also known as prebinding), while method override implements run-time polymorphism (also known as postbinding). Runtime polymorphism is the most essential thing about object-oriented. To implement polymorphism, two things need to be done: 1. Method rewriting (the subclass inherits the parent class and rewrites existing or abstract methods in the parent class); 2. Object modeling (referring to the child type object with the parent type reference, so that the same reference calls the same method will show different behaviors according to the different subclass objects).
2. What is the difference between accessing modifiers public, private, protected, and not writing (default)?
Answer: The differences are as follows:
Scope is the same as the bun subclass.
public √ √ √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
The default is default when the class members do not write access modification. By default, it is equivalent to public for other classes in the same package, and private for other classes that are not in the same package. Protected is equivalent to public to subclasses, and private to classes that are not in the same package that have no parent-child relationship.
3. Is String the most basic data type?
Answer: No. There are only 8 basic data types in Java: byte, short, int, long, float, double, char, and boolean; except for the basic type (primitive type) and enumeration type (enumeration type), the rest are reference types (reference type).
4. float f=3.4; Is it correct?
Answer: Incorrect. 3.4 is a double precision number. Assigning double to floating point type (float) will cause accuracy loss (down-casting, also known as narrowing), so you need to cast float f =(float)3.4; or write float f =3.4F;.
5. Short s1 = 1; s1 = s1 + 1; Is there anything wrong? short s1 = 1; s1 += 1; Is there something wrong?
Answer: For short s1 = 1; s1 = s1 + 1; Since 1 is an int type, the result of s1+1 operation is also an int type, and a cast type is required to assign value to the short type. And short s1 = 1; s1 += 1; can be compiled correctly because s1+= 1; is equivalent to s1 = (short)(s1 + 1); there are implicit casts.
6. Is there a goto in Java?
Answer: goto is a reserved word in Java and is not used in the current version of Java. (A list of Java keywords is given in the appendix of the book "The Java Programming Language" written by James Gosling (the father of Java), which includes goto and const, but these two are keywords that are currently unusable, so some places call it reserved words. In fact, the word reserved words should have a broader meaning, because programmers familiar with C language know that words or combinations of words that have special meanings used in the system library are considered reserved words)
7. What is the difference between int and Integer?
Answer: Java is an almost pure object-oriented programming language, but for the sake of programming convenience, it still introduces basic data types that are not objects. However, in order to operate these basic data types as objects, Java has introduced the corresponding wrapper class for each basic data type. The packaging class of int is Integer. Since JDK 1.5, an automatic packing/unboxing mechanism has been introduced, so that the two can be converted to each other.
Java provides wrapper types for each primitive type:
Primitive types: boolean, char, byte, short, int, long, float, double
Packaging Types: Boolean, Character, Byte, Short, Integer, Long, Float, Double
package com.lovo; // Why ask about hovertree.compublic class AutoUnboxingTest { public static void main(String[] args) { Integer a = new Integer(3); Integer b = 3; // Automatic box 3 into Integer type int c = 3; System.out.println(a == b); // false The two references do not reference the same object System.out.println(a == c); // true a automatically unboxes into int type and then compares with c} }Added: I recently encountered an interview question, which is also related to automatic packing and unboxing, 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); } } // hovertree.comIf you don't understand it, it's easy to think that both outputs are either true or false. First of all, it is important to note that the four variables f1, f2, f3, and f4 are all Integer objects, so the following == operation compares not values but references. What is the essence of packing? When we assign an int value to an Integer object, we will call the static method valueOf of the Integer class. If we look at the source code of valueOf, we will know what is going on.
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } // hovertree.comIntegerCache is an 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. * hovertree.com */ 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 internalized (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }Simply put, if the literal value is between -128 and 127, then the new Integer object will not be new, but the Integer object in the constant pool will be directly referenced. Therefore, the result of f1==f2 in the above interview question is true, and the result of f3==f4 is false. The simpler the interview questions, the more mystery there are, and the interviewer needs to have considerable skills.
8. What is the difference between & and &&?
Answer: There are two uses of the & operator: (1) bitwise and (2) logical and. The && operator is a short circuit and operation. The difference between logic and short circuits is very huge, although both require that the Boolean values at the left and right ends of the operator are true to the value of the entire expression. && is called a short-circuit operation because if the value of the expression on the left of && is false, the expression on the right will be short-circuited directly and the operation will not be performed. Many times we may need to use && instead of &. For example, when verifying that the user name is not null and is not an empty string, it should be written as: username != null &&!username.equals(""). The order of the two cannot be exchanged, and the & operator cannot be used, because if the first condition is not true, the equals comparison of the string cannot be performed at all, otherwise a NullPointerException will be generated. Note: The same is true for the difference between logical or operator (|) and short-circuit or operator (||).
Added: If you are familiar with JavaScript, you may be able to feel the power of short-circuit computing more. If you want to become a master of JavaScript, start by playing short-circuit computing.
9. Explain the usage of stack, heap and static storage areas in memory.
Answer: Usually we define a variable of the basic data type, an object reference, and the on-site storage of function calls all use the stack space in memory; and the objects created through the new keyword and constructor are placed in the heap space; the literals in the program, such as 100, "hello" and constants written directly are placed in the static storage area. The stack space operates the fastest but is also very small. Usually a large number of objects are placed in the heap space, and the entire memory, including the virtual memory on the hard disk, can be used as heap space.
String str = new String("hello");
In the above statement, str is placed on the stack, the string object created with new is placed on the heap, and the literal "hello" is placed on the static storage area.
Supplement: A newer version of Java uses a technology called "escape analysis" that can place some local objects on the stack to improve the operational performance of objects.
10. What is Math.round(11.5) equal to? What is Math.round(-11.5) equal to?
Answer: The return value of Math.round(11.5) is 12, and the return value of Math.round(-11.5) is -11. The principle of rounding is to add 0.5 to the parameter and then round it down.
11. Can swtich act on byte, long act on String?
Answer: In the early JDK, in switch (expr), expr can be byte, short, char, and int. Starting from version 1.5, Java has introduced enum types (enums), and expr can also be enums, starting from version 1.7 of JDK, and also a string (String). Long type is not allowed.
12. Use the most efficient method to calculate 2 times 8?
Answer: 2 << 3 (moving 3 bits on the left is equivalent to multiplying by 2 to the power of 3, and moving 3 bits on the right is equivalent to dividing by 2 to the power of 3).
Supplement: When we rewrite the hashCode method for the class we wrote, we may see the code shown below. In fact, we don’t quite understand why we use such multiplication to generate a hash code (hash code), and why is this number a prime number, and why is the number 31 usually selected? You can Baidu on the answers to the first two questions. Choose 31 because shift and subtraction operations can be used instead of multiplication, thereby achieving better performance. Speaking of this, you may have thought of: 31 * num <==> (num << 5) - num, shifting the left 5 bits is equivalent to multiplying by 2 to the 5th power (32) and subtracting itself is equivalent to multiplying by 31. All VMs can automatically complete this optimization.
package com.loonstudio; public class PhoneNumber { private int areaCode; private String prefix; private String lineNumber; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + areaCode; result = prime * result + ((lineNumber == null) ? 0 : lineNumber.hashCode()); result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PhoneNumber other = (PhoneNumber) obj; if (areaCode != other.areaCode) return false; if (lineNumber == null) { if (other.lineNumber != null) return false; } else if (!lineNumber.equals(other.lineNumber)) return false; if (prefix == null) { if (other.prefix != null) return false; } else if (!prefix.equals(other.prefix)) return false; return true; } } //Why ask about hovertree.com13. Is there a length() method for arrays? Is there a length() method for String?
Answer: The array does not have a length() method, but has a length attribute. String has a length() method. In JavaScript, obtaining the length of the string is obtained through the length attribute, which is easily confused with Java.
14. In Java, how to break out of the current multiple nested loops?
Answer: Add a mark such as A before the outermost loop, and then use break A; multiple loops can be broken. (Java supports tagged break and continue statements, and their functions are a bit similar to goto statements in C and C++, but just like avoiding goto, you should avoid tagged break and continue because it will not make your program more elegant, and often even have the opposite effect, so this syntax is actually better.)
15. Can the constructor be override?
Answer: The constructor cannot be inherited, so it cannot be rewritten, but it can be overloaded.
16. Two objects have the same value (x.equals(y) == true), but they can have different hash codes. Is this right?
Answer: No, if the two objects x and y satisfy x.equals(y) == true, their hash code should be the same. Java stipulates the eqauls method and hashCode method as follows: (1) If two objects are the same (equals method returns true), then their hashCode values must be the same; (2) If the hashCodes of the two objects are the same, they are not necessarily the same. Of course, you don't have to do as required, but if you violate the above principles, you will find that when using containers, the same object can appear in the Set collection, and the efficiency of adding new elements will be greatly reduced (for systems using hash storage, frequent conflicts in hash codes will cause a sharp decline in access performance).
Supplement: Many Java programs know about equals and hashCode methods, but many people just know it. In Joshua Bloch's masterpiece "Effective Java" (many software companies, "Effective Java", "Java Programming Thoughts" and "Refactoring: Improving the Quality of Existing Code" are must-read books by Java programmers. If you haven't read it, hurry up and buy one on Amazon.) This is how to introduce the equals method: First of all, the equals method must meet the reflexivity (x.equals(x) must return true), and symmetry (x.equals(y) returns true, y.equals(x) must also be It must return true), transitiveness (x.equals(y) and y.equals(z) must also return true) and consistency (when the object information referenced by x and y is not modified, multiple calls to x.equals(y) should get the same return value), and for any non-null reference x, x.equals(null) must return false. The tricks to implementing high-quality equals methods include: 1. Use the == operator to check "whether the parameter is a reference to this object"; 2. Use the instanceof operator to check "whether the parameter is the correct type"; 3. For key attributes in the class, check whether the attributes passed to the object match it; 4. After writing the equals method, ask yourself whether it satisfies symmetry, transitiveness, and consistency; 5. Always rewrite hashCode when rewriting equals; 6. Do not replace the Object object in the equals method parameters with other types, and do not forget the @Override annotation when rewriting.
17. Can the String class be inherited?
Answer: The String class is a final class and cannot be inherited.
Supplement: Inheriting String is a wrong behavior in itself. The best way to reuse String types is association (HAS-A) rather than inheritance (IS-A).
18. When an object is passed as a parameter to a method, this method can change the properties of the object and return the changed result. So is it a value pass or a reference pass here?
Answer: It is value transfer. The Java programming language only passes parameters with values. When an object instance is passed into a method as a parameter, the value of the parameter is a reference to the object. The properties of an object can be changed during the call process, but the reference to the object will never change. In C++ and C#, the value of the passed parameters can be changed by passing references or transferring out parameters.
Supplement: It is really inconvenient to not pass references in Java, which has not been improved in Java 8. It is precisely this way that a large number of Wrapper classes appear in the code written in Java (placing references that need to be modified through method calls into a Wrapper class, and then passing the Wrapper object into a method). This approach will only make the code bloated, especially for developers who transform from C and C++ to Java programmers to intolerable.
19. What is the difference between String and StringBuilder and StringBuffer?
Answer: The Java platform provides two types of strings: String and StringBuffer/StringBuilder, which can store and manipulate strings. Where String is a read-only string, which means that the content of the string referenced by String cannot be changed. The string objects represented by the StringBuffer and StringBuilder classes can be modified directly. StringBuilder was introduced in JDK 1.5. It is exactly the same as StringBuffer's method, the difference is that it is used in a single threaded environment because all aspects of it are not modified by synchronized, so it is slightly more efficient than StringBuffer.
Supplement 1: There is an interview question: Is there any situation where using + to do string concatenation is better than calling the append method of the StringBuffer/StringBuilder object? If the string obtained after the connection already exists in the static storage area, then using + for string concatenation is better than the append method of StringBuffer/StringBuilder.
Supplement 2: The following is also an interview question, asking the output of the program to see if you can give the correct answer.
package com.lovo; //Why ask about hovertree.compublic class StringEqualTest { public static void main(String[] args) { String a = "Programming"; String b = new String("Programming"); String c = "Program" + "ming"; System.out.println(a == b); System.out.println(a == c); System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(a.intern() == b.intern()); } }20. The difference between overload and override. Can overloaded methods be distinguished based on the return type?
Answer: Both method overloading and rewriting are ways to implement polymorphism. The difference is that the former implements compile-time polymorphism, while the latter implements run-time polymorphism. Overload occurs in a class. If a method with the same name has a different parameter list (different parameter types, different number of parameters, or both), it is considered an overload; rewriting occurs between the subclass and the parent class. Rewriting requires that the subclass's rewritten method and the parent class have the same return type as the parent class's rewritten method, which is better access than the parent class's rewritten method, and cannot declare more exceptions than the parent class's rewritten method (Rischer's substitution principle). Overloading does not have special requirements for return types.
Supplement: Huawei once asked a question in the interview question: Why can't you distinguish overloading based on the return type and tell your answer!
21. Describe the principle and mechanism of JVM loading class files?
Answer: The loading of classes in the JVM is implemented by a class loader (ClassLoader) and its subclasses. The class loader in Java is an important Java runtime system component, which is responsible for finding and loading classes in class files at runtime.
Replenish:
1. Due to the cross-platform nature of Java, the 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, connected (verified, prepared and parsed) and initialized. Class loading refers to reading data from the class .class file into memory. Usually, creating a byte array to read it into the .class file, and then generating a Class object corresponding to the loaded class. After the loading is completed, the Class object is still incomplete, so the class is not available at this time. When the class is loaded, it enters the connection stage. This stage includes three steps: verification, preparation (allocating memory for static variables and setting the default initial value) and parsing (replace symbol references with direct references). Finally, the JVM initializes the class, including: 1. If the class has a direct parent class and the class has not been initialized, then the parent class will be initialized first; 2. If there are initialization statements in the class, these initialization statements will be executed in turn.
2. Class loading is done by class loader, which includes: root loader (BootStrap), extension loader (Extension), system loader (System) and user-defined class loader (subclass of java.lang.ClassLoader). Starting from JDK 1.2, the class loading process adopts the father delegation mechanism (PDM). PDM better ensures the security of the Java platform. In this mechanism, the JVM's own Bootstrap is the root loader, and other loaders have and only have one parent class loader. The class loading first requests the parent class loader to load, and the parent class loader will only be loaded by its subclass loader when it is powerless. The JVM does not provide references to Bootstrap to Java programs. Here are some instructions for several class loaders:
a) Bootstrap: It is generally implemented using local code and is responsible for loading the basic core class library of JVM (rt.jar);
b) Extension: Load the class library from the directory specified by the java.ext.dirs system property, and its parent loader is Bootstrap;
c)System: also known as application class loader, its parent class is Extension. It is the most widely used class loader. It records classes from the directory specified by the environment variable classpath or system attribute java.class.path, and is the default parent loader of the user-defined loader.
22. Can a Chinese character be stored in a char type variable? Why?
Answer: The char type can store a Chinese character, because the encoding used in Java is Unicode (no specific encoding is selected, and characters are directly used in the character set number, which is the only unified method). A char type takes up 2 bytes (16bit), so it is no problem to put a Chinese.
Supplement: Using Unicode means that characters have different manifestations inside and outside the JVM, and are both Unicode inside the JVM. When this character is transferred from the JVM to the outside (for example, stored in the file system), encoding conversion is required. Therefore, Java has byte streams and character streams, as well as conversion streams that convert between character streams and byte streams, such as InputStreamReader and OutputStreamReader. These two classes are adapter classes between byte streams and character streams, and undertake the task of encoding conversion; for C programmers, to complete such encoding conversion, they probably rely on the characteristics of union (union/community) shared memory to achieve.
23. What are the similarities and differences between abstract class and interface?
Answer: Both abstract classes and interfaces cannot be instantiated, but references to abstract classes and interface types can be defined. If a class inherits an abstract class or implements an interface, it needs to implement all the abstract methods in it, otherwise the class still needs to be declared as an abstract class. Interfaces are more abstract than abstract classes, because constructors can be defined in abstract classes, and there can be abstract methods and concrete methods, while constructors cannot be defined in interfaces, and all methods in them are abstract methods. Members in abstract classes can be private, default, protected, and public, while members in interfaces are all public. Member variables can be defined in abstract classes, while member variables defined in interfaces are actually constants. Classes with abstract methods must be declared as abstract classes, and abstract classes do not necessarily have abstract methods.
24. What is the difference between static nested classes and inner classes (Inner Class)?
Answer: Static Nested Class is an inner class declared as static, which can be instantiated without relying on external class instances. The usual inner classes need to be instantiated after the external class is instantiated, and the syntax looks quite weird, as shown below.
package com.lovo; /** * Poker class (a deck of poker) Why ask about hovertree.com * */ public class Poker { private static String[] suites = {"spade", "rose", "grass flower", "cube"}; private static int[] faces = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; private Card[] cards; /** * Constructor* */ public Poker() { cards = new Card[52]; for(int i = 0; i < suites.length; i++) { for(int j = 0; j < faces.length; j++) { cards[i * 13 + j] = new Card(suites[i], faces[j]); } } } /** * Shuffle (random out of order) * */ public void shuffle() { 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; } } /** * Card deal* @param index The position of the deal* */ public Card deal(int index) { return cards[index]; } /** * Card class (a piece of poker) * [Internal class] * @author Luo Hao* */ public class Card { private String suite; // suit private int face; // points public Card(String suite, int face) { this.suite = suite; this.face = face; } @Override public String toString() { String faceStr = ""; switch(face) { case 1: faceStr = "A"; break; case 11: faceStr = "J"; break; case 12: faceStr = "Q"; break; case 13: faceStr = "K"; break; default: faceStr = String.valueOf(face); } return suite + faceStr; } } } Test class:
package com.lovo; class PokerTest { public static void main(String[] args) { Poker poker = new Poker(); poker.shuffle(); // Shuffle Poker.Card c1 = poker.deal(0); // Serves the first card// For non-static internal class Cards // Can Card object be created only through its external class Poker object Poker.Card c2 = poker.new Card("Red Heart", 1); // Create a card yourself System.out.println(c1); // The first System.out.println(c2); // Print: Red Heart A } } //Why ask about hovertree.com25. Will there be a memory leak in Java? Please describe it briefly.
Answer: In theory, Java will not have memory leaks because it has a garbage collection mechanism (GC) (this is also an important reason why Java is widely used in server-side programming); however, in actual development, there may be useless but accessible objects, and these objects cannot be recycled by GC and memory leaks will occur. An example is that the objects in Hibernate's Session (level one cache) are persistent, and the garbage collector will not recycle these objects, but there may be useless garbage objects in these objects. The following example also shows the memory leak in Java:
package com.lovo; //Why ask about hovertree.comimport java.util.Arrays; import java.util.EmptyStackException; public class MyStack<T> { private T[] elements; private int size = 0; private static final int INIT_CAPACITY = 16; public MyStack() { elements = (T[]) new Object[INIT_CAPACITY]; } public void push(T elem) { ensureCapacity(); elements[size++] = elem; } public T pop() { if(size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity() { if(elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); } } }The above code implements a stack (first-in-and-out (FILO)) structure that doesn't seem to have any obvious problems at first glance, and it can even pass through various unit tests you write. However, the pop method has a memory leak problem. When we use the pop method to pop objects on the stack, the object will not be treated as garbage collection, even if the program using the stack no longer refers to these objects, because the stack maintains an obsolete reference to these objects. In languages that support garbage collection, memory leaks are very hidden, and this memory leak is actually unconscious object maintenance. If an object reference is unconsciously retained, the garbage collector will not process the object, nor will it process other objects referenced by the object. Even if there are only a few such objects, it may cause many objects to be excluded from garbage collection, which will have a significant impact on performance. In extreme cases, Disk Paging (physical memory exchanges data with virtual memory of hard disk), and even cause OutOfMemoryError.
26. Can abstract methods be static at the same time, can they be native at the same time, and can they be modified by synchronized at the same time?
Answer: None of them. Abstract methods require subclass rewriting, while static methods cannot be rewritten, so the two are contradictory. Local methods are methods implemented by local code (such as C code), and abstract methods are not implemented and are also contradictory. Synchronized is related to the implementation details of the method. Abstract methods do not involve implementation details, so they are also contradictory.
27. What is the difference between static variables and instance variables?
Answer: Static variables are variables modified by static modifiers, also known as class variables. They belong to a class and do not belong to any object of the class. No matter how many objects a class creates, the static variable has and only one copy in memory; instance variables must depend on a certain instance, and the object needs to be created first and then through the object to access it. Static variables can enable multiple objects to share memory. In Java development, context and tool classes usually have a large number of static members.
28. Is it possible to issue a call to a non-static method from within a static method?
Answer: No, a static method can only access static members, because non-static method calls must first create an object, so the object may not be initialized when calling a static method.
29. How to implement object cloning?
Answer: There are two ways:
1. Implement the Cloneable interface and override the clone() method in the Object class;
2. Implement the Serializable interface, and implement cloning through object serialization and deserialization, which can realize true deep cloning. The code is as follows.
package com.lovo; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class MyUtil { private MyUtil() { throw new AssertionError(); } public static <T> 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: There is no point in calling the close method of ByteArrayInputStream or ByteArrayOutputStream object // These two memory-based streams can free resources as long as the garbage collector cleans up the object} } //Who asks about hovertree.com Here is the test code:
package com.lovo; import java.io.Serializable; /** * 人类* @author 骆昊* */ class Person implements Serializable { private static final long serialVersionUID = -9102017020286042305L; private String name; // 姓名private int age; // 年龄private Car car; // 座驾public Person(String name, int age, Car car) { this.name = name; this.age = age; this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; } } /** * 小汽车类* @author 骆昊* */ class Car implements Serializable { private static final long serialVersionUID = -5713945027627603702L; private String brand; // 品牌private int maxSpeed; // 最高时速public Car(String brand, int maxSpeed) { this.brand = brand; this.maxSpeed = maxSpeed; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } @Override public String toString() { return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]"; } } //何问起hovertree.comclass CloneTest { public static void main(String[] args) { try { Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300)); Person p2 = MyUtil.clone(p1); // 深度克隆p2.getCar().setBrand("BYD"); // 修改克隆的Person对象p2关联的汽车对象的品牌属性// 原来的Person对象p1关联的汽车不会受到任何影响// 因为在克隆Person对象时其关联的汽车对象也被克隆了System.out.println(p1); } catch (Exception e) { e.printStackTrace(); } } }注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。
30、GC 是什么?为什么要有GC?
答: GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
与垃圾回收相关的JVM参数:
-Xms / -Xmx --- 堆的初始大小/ 堆的最大大小
-Xmn --- 堆中年轻代的大小
-XX:-DisableExplicitGC --- 让System.gc()不产生任何作用
-XX:+PrintGCDetail --- 打印GC的细节
-XX:+PrintGCDateStamps --- 打印GC操作的时间戳
31、String s=new String(“xyz”);创建了几个字符串对象?
答:两个对象,一个是静态存储区的"xyz",一个是用new创建在堆上的对象。
32、接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)?
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承具体类,但前提是具体类必须有明确的构造函数。
33、一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。
34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?
答:可以继承其他类或实现其他接口,在Swing编程中常用此方式来实现事件监听和回调。
35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
36、Java 中的final关键字有哪些用法?
答: (1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
37、指出下面程序的运行结果:
class A{ static{ System.out.print("1"); } public A(){ System.out.print("2"); } } class B extends A{ static{ System.out.print("a"); } public B(){ System.out.print("b"); } } //何问起hovertree.compublic class Hello{ public static void main(String[] args){ A ab = new B(); ab = new B(); } }答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
38、数据类型之间的转换:
1)如何将字符串转换为基本数据类型?
2)如何将基本数据类型转换为字符串?
answer:
1)调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;
2)一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf(…)方法返回相应字符串
39、如何实现字符串的反转及替换?
答:方法很多,可以自己写实现也可以使用String或StringBuffer / StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:
public static String reverse(String originStr) { if(originStr == null || originStr.length() <= 1) return originStr; return reverse(originStr.substring(1)) + originStr.charAt(0); } //何问起hovertree.com40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?
答:代码如下所示:
String s1 = "你好";String s2 = newString(s1.getBytes("GB2312"), "ISO-8859-1");41、日期和时间:
1)如何取得年月日、小时分钟秒?
2)如何取得从1970年1月1日0时0分0秒到现在的毫秒数?
3)如何取得某月的最后一天?
4)如何格式化日期?
答:操作方法如下所示:
1)创建java.util.Calendar 实例,调用其get()方法传入不同的参数即可获得参数所对应的值
2)以下方法均可获得该毫秒数:
Calendar.getInstance().getTimeInMillis(); System.currentTimeMillis(); //何问起hovertree.com
3)示例代码如下:
Calendar time = Calendar.getInstance(); time.getActualMaximum(Calendar.DAY_OF_MONTH); //何问起hovertree.com
4)利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。
42、打印昨天的当前时刻。
answer:
public class YesterdayCurrent { public static void main(String[] args){ Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); System.out.println(cal.getTime()); } } //何问起hovertree.com43、比较一下Java 和JavaSciprt。
答: JavaScript 与Java是两个公司开发的不同的两个产品。Java 是原Sun 公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言,它的前身是LiveScript;而Java 的前身是Oak语言。
下面对两种语言间的异同作如下比较:
1)基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;
2)解释和编译:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;
3)强类型变量和类型弱变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量声明,采用其弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;
4)代码格式不一样。
补充:上面列出的四点是原来所谓的标准答案中给出的。其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。目前的编程语言的发展趋势是函数式语言和动态语言。在Java中类(class)是一等公民,而JavaScript中函数(function)是一等公民。对于这种问题,在面试时还是用自己的语言回答会更加靠谱。
44、什么时候用assert?
答: assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后, assertion检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式计算为false,那么系统会报告一个AssertionError。
断言用于调试目的:
assert(a > 0); // throws an AssertionError if a <= 0
断言可以有两种形式:
assert Expression1;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。
断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用-enableassertions 或者-ea 标记。
要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。
要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。
45、Error 和Exception 有什么区别?
答: Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
补充: 2005年摩托罗拉的面试中曾经问过这么一个问题“If a process reports a stack overflow run-time error, what's the most possible cause?”,给了四个选项a. lack of memory; b. write on an invalid memory space; c. recursive function calling; d. array index out of boundary. Java程序在运行时也可能会遭遇StackOverflowError,这是一个错误无法恢复,只能重新修改代码了,这个面试题的答案是c。如果写了不能迅速收敛的递归,则很有可能引发栈溢出的错误,如下所示:
package com.lovo; public class StackOverflowErrorTest { public static void main(String[] args) { main(null); } } //何问起hovertree.com因此,用递归编写程序时一定要牢记两点:1. 递归公式;2. 收敛条件(什么时候就不再递归而是回溯了)。
46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。
47、Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?
答: Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw 语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的try 语句。
48、运行时异常与受检异常有何异同?
答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《Effective Java》中对异常的使用给出了以下指导原则:
不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)
对可以恢复的情况使用受检异常,对编程错误使用运行时异常避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)
优先使用标准的异常每个方法抛出的异常都要有文档保持异常的原子性不要在catch中忽略掉捕获到的异常
49、列出一些你常见的运行时异常?
answer:
ArithmeticException(算术异常)
ClassCastException (类转换异常)
IllegalArgumentException (非法参数异常)
IndexOutOfBoundsException (下表越界异常)
NullPointerException (空指针异常)
SecurityException (安全异常)
50、final, finally, finalize 的区别?
答: final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final 的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final 的方法也同样只能使用,不能在子类中被重写。finally:通常放在try…catch的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。finalize:Object类中定义的方法,Java中允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize() 方法可以整理系统资源或者执行其他清理工作。
以上就是本文的全部内容,希望对大家参加Java面试有所帮助,也希望大家多多支持武林网。