Summary of 2020 new Java basic interview questions
Oct 21, 2020 pm 04:51 PMThe difference between ==, equals and hashCode in java
(More interview question recommendations: java interview questions and answers)
1, ==
Data types in Java can be divided into two categories:
Basic data types, also called primitive data types To compare byte, short, char, int, long, float, double, boolean, use the double equal sign (==), and compare their values.
Reference type (class, interface, array) When they compare using (==), they compare their storage addresses in memory. Therefore, unless they are the same new object, the result of their comparison is true, otherwise the result of the comparison is false. Objects are placed on the heap, and the reference (address) of the object is stored on the stack. First look at the virtual machine memory map and code:
public?class?testDay?{ ????public?static?void?main(String[]?args)?{ ????????String?s1?=?new?String("11"); ????????String?s2?=?new?String("11"); ????????System.out.println(s1?==?s2); ????????System.out.println(s1.equals(s2)); ????} }
The result is:
false
true

Both s1 and s2 store the addresses of the corresponding objects. Therefore, if s1== s2 is used, the address values ??of the two objects are compared (that is, whether the references are the same), which is false. When calling the equals direction, the value in the corresponding address is compared, so the value is true. Here we need to describe equals() in detail.
2. Detailed explanation of equals() method
The equals() method is used to determine whether other objects are equal to this object. It is defined in Object, so any object has the equals() method. The difference is whether the method is overridden or not.
Let’s take a look at the source code first:
public?boolean?equals(Object?obj)?{????return?(this?==?obj); }
Obviously, Object defines a comparison of the address values ??of two objects (that is, comparing whether the references are the same). But why does calling equals() in String compare not the address but the value in the heap memory address? Here is the key point. When encapsulation classes such as String, Math, Integer, Double, etc. use the equals() method, they have already covered the equals() method of the object class. Take a look at the rewritten equals() in String:
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; }
After rewriting, this is the content comparison, and it is no longer the comparison of the previous address. By analogy, classes such as Math, Integer, Double, etc. all override the equals() method to compare contents. Of course, basic types perform value comparisons.
It should be noted that when the equals() method is overridden, hashCode() will also be overridden. According to the implementation of the general hashCode() method, equal objects must have equal hashcodes. Why is this so? Here we briefly mention hashcode.
3. A brief discussion of hashcode()
It is obviously a question about the difference between ==, equals and hashCode in Java, but why is it suddenly related to hashcode(). You must be very depressed, okay, let me give a simple example and you will know why hashCode is involved when == or equals.
For example: If you want to find out whether a collection contains an object, how should you write the program? If you don't use the indexOf method, just traverse the collection and compare whether you think of it. What if there are 10,000 elements in the collection, it would be tiring, right? So in order to improve efficiency, the hash algorithm was born. The core idea is to divide the collection into several storage areas (can be seen as buckets). Each object can calculate a hash code and can be grouped according to the hash code. Each group corresponds to a certain storage area. In this way, an object can be grouped according to the hash code. Its hash code can be divided into different storage areas (different areas).
So when comparing elements, the hashcode is actually compared first, and if they are equal, the equal method is compared.
Look at the hashcode diagram:

#An object generally has a key and a value, and its hashCode value can be calculated based on the key. Then it is stored in different storage areas according to its hashCode value, as shown in the figure above. Multiple values ??can be stored in different areas because hash conflicts are involved. Simple: If the hashCode of two different objects is the same, this phenomenon is called a hash conflict. Simply put, it means the hashCode is the same but equals is a different value. For comparing 10,000 elements, there is no need to traverse the entire collection. You only need to calculate the hashCode of the key of the object you want to find, and then find the storage area corresponding to the hashCode. The search is over.

大概可以知道,先通過hashcode來比較,如果hashcode相等,那么就用equals方法來比較兩個對象是否相等。再重寫了equals最好把hashCode也重寫。其實(shí)這是一條規(guī)范,如果不這樣做程序也可以執(zhí)行,只不過會隱藏bug。一般一個類的對象如果會存儲在HashTable,HashSet,HashMap等散列存儲結(jié)構(gòu)中,那么重寫equals后最好也重寫hashCode。
總結(jié):
- hashCode是為了提高在散列結(jié)構(gòu)存儲中查找的效率,在線性表中沒有作用。
- equals重寫的時候hashCode也跟著重寫
- 兩對象equals如果相等那么hashCode也一定相等,反之不一定。
2. int、char、long 各占多少字節(jié)數(shù)
byte 是 字節(jié)
bit 是 位
1 byte = 8 bit
char在java中是2個字節(jié),java采用unicode,2個字節(jié)來表示一個字符
short 2個字節(jié)
int 4個字節(jié)
long 8個字節(jié)
float 4個字節(jié)
double 8個字節(jié)
3. int和Integer的區(qū)別
- Integer是int的包裝類,int則是java的一種基本數(shù)據(jù)類型
- Integer變量必須實(shí)例化后才能使用,而int變量不需要
- Integer實(shí)際是對象的引用,當(dāng)new一個Integer時,實(shí)際上是生成一個指針指向此對象;而int則是直接存儲數(shù)據(jù)值
- Integer的默認(rèn)值是null,int的默認(rèn)值是0
延伸: 關(guān)于Integer和int的比較
- 由于Integer變量實(shí)際上是對一個Integer對象的引用,所以兩個通過new生成的Integer變量永遠(yuǎn)是不相等的(因?yàn)閚ew生成的是兩個對象,其內(nèi)存地址不同)。
Integer?i?=?new?Integer(100); Integer?j?=?new?Integer(100); System.out.print(i?==?j);?//false
- Integer變量和int變量比較時,只要兩個變量的值是向等的,則結(jié)果為true(因?yàn)榘b類Integer和基本數(shù)據(jù)類型int比較時,java會自動拆包裝為int,然后進(jìn)行比較,實(shí)際上就變?yōu)閮蓚€int變量的比較)
Integer?i?=?new?Integer(100); int?j?=?100; System.out.print(i?==?j);?//true
- 非new生成的Integer變量和new Integer()生成的變量比較時,結(jié)果為false。(因?yàn)榉莕ew生成的Integer變量指向的是java常量池中的對象,而new Integer()生成的變量指向堆中新建的對象,兩者在內(nèi)存中的地址不同)
Integer?i?=?new?Integer(100); Integer?j?=?100; System.out.print(i?==?j);?//false
- 對于兩個非new生成的Integer對象,進(jìn)行比較時,如果兩個變量的值在區(qū)間-128到127之間,則比較結(jié)果為true,如果兩個變量的值不在此區(qū)間,則比較結(jié)果為false
Integer?i?=?100; Integer?j?=?100; System.out.print(i?==?j);?//true
Integer?i?=?128; Integer?j?=?128; System.out.print(i?==?j);?//false
對于第4條的原因: java在編譯Integer i = 100 ;時,會翻譯成為Integer i = Integer.valueOf(100);,而java API中對Integer類型的valueOf的定義如下:
public?static?Integer?valueOf(int?i){ ????assert?IntegerCache.high?>=?127;????if?(i?>=?IntegerCache.low?&&?i?<p>java對于-128到127之間的數(shù),會進(jìn)行緩存,Integer i = 127時,會將127進(jìn)行緩存,下次再寫Integer j = 127時,就會直接從緩存中取,就不會new了</p><h2 class="heading" data-id="heading-6">4. java多態(tài)的理解</h2><h3 class="heading" data-id="heading-7">1.多態(tài)概述</h3><ol> <li><p>多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦浴?lt;/p></li> <li><p>多態(tài)現(xiàn)實(shí)意義理解:</p></li> </ol>
現(xiàn)實(shí)事物經(jīng)常會體現(xiàn)出多種形態(tài),如學(xué)生,學(xué)生是人的一種,則一個具體的同學(xué)張三既是學(xué)生也是人,即出現(xiàn)兩種形態(tài)。
Java作為面向?qū)ο蟮恼Z言,同樣可以描述一個事物的多種形態(tài)。如Student類繼承了Person類,一個Student的對象便既是Student,又是Person。
多態(tài)體現(xiàn)為父類引用變量可以指向子類對象。
前提條件:必須有子父類關(guān)系。
注意:在使用多態(tài)后的父類引用變量調(diào)用方法時,會調(diào)用子類重寫后的方法。
- 多態(tài)的定義與使用格式
定義格式:父類類型 變量名=new 子類類型();
2.多態(tài)中成員的特點(diǎn)
- 多態(tài)成員變量:編譯運(yùn)行看左邊
Fu f=new Zi();
System.out.println(f.num);//f是Fu中的值,只能取到父中的值
- 多態(tài)成員方法:編譯看左邊,運(yùn)行看右邊
Fu f1=new Zi();
System.out.println(f1.show());//f1的門面類型是Fu,但實(shí)際類型是Zi,所以調(diào)用的是重寫后的方法。
3.instanceof關(guān)鍵字
作用:用來判斷某個對象是否屬于某種數(shù)據(jù)類型。
*?注意:?返回類型為布爾類型
使用案例:
Fu?f1=new?Zi(); Fu?f2=new?Son();if(f1?instanceof?Zi){ ????System.out.println("f1是Zi的類型"); }else{ ????System.out.println("f1是Son的類型"); }
4.多態(tài)的轉(zhuǎn)型
多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型和向下轉(zhuǎn)型兩種
-
向上轉(zhuǎn)型:多態(tài)本身就是向上轉(zhuǎn)型過的過程
使用格式:父類類型 變量名=new 子類類型();
適用場景:當(dāng)不需要面對子類類型時,通過提高擴(kuò)展性,或者使用父類的功能就能完成相應(yīng)的操作。
-
向下轉(zhuǎn)型:一個已經(jīng)向上轉(zhuǎn)型的子類對象可以使用強(qiáng)制類型轉(zhuǎn)換的格式,將父類引用類型轉(zhuǎn)為子類引用各類型
使用格式:子類類型 變量名=(子類類型)父類類型的變量;
適用場景:當(dāng)要使用子類特有功能時。
5.多態(tài)案例:
例1:
package?day0524; ? public?class?demo04?{ ????public?static?void?main(String[]?args)?{ ????????People?p=new?Stu(); ????????p.eat(); ????????//調(diào)用特有的方法 ????????Stu?s=(Stu)p; ????????s.study(); ????????//((Stu)?p).study(); ????} } class?People{ ????public?void?eat(){ ????????System.out.println("吃飯"); ????} } class?Stu?extends?People{ ????@Override ????public?void?eat(){ ????????System.out.println("吃水煮肉片"); ????} ????public?void?study(){ ????????System.out.println("好好學(xué)習(xí)"); ????} } class?Teachers?extends?People{ ????@Override ????public?void?eat(){ ????????System.out.println("吃櫻桃"); ????} ????public?void?teach(){ ????????System.out.println("認(rèn)真授課"); ????} }
答案:吃水煮肉片 好好學(xué)習(xí)
例2:
請問題目運(yùn)行結(jié)果是什么?
package?day0524; public?class?demo1?{ ????public?static?void?main(String[]?args)?{ ????????A?a=new?A(); ????????a.show(); ????????B?b=new?B(); ????????b.show(); ????} } class?A{ ????public?void?show(){ ????????show2(); ????} ????public?void?show2(){ ????????System.out.println("A"); ????} } class?B?extends?A{ ????public?void?show2(){ ????????System.out.println("B"); ????} } class?C?extends?B{ ????public?void?show(){ ????????super.show(); ????} ????public?void?show2(){ ????????System.out.println("C"); ????} }
答案:A B
5. String、StringBuffer和StringBuilder區(qū)別
1、長度是否可變
- String 是被 final 修飾的,他的長度是不可變的,就算調(diào)用 String 的concat 方法,那也是把字符串拼接起來并重新創(chuàng)建一個對象,把拼接后的 String 的值賦給新創(chuàng)建的對象
- StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象,StringBuffer 與 StringBuilder 中的方法和功能完全是等價的。調(diào)用StringBuffer 的 append 方法,來改變 StringBuffer 的長度,并且,相比較于 StringBuffer,String 一旦發(fā)生長度變化,是非常耗費(fèi)內(nèi)存的!
2、執(zhí)行效率
- 三者在執(zhí)行速度方面的比較:StringBuilder > StringBuffer > String
3、應(yīng)用場景
- 如果要操作少量的數(shù)據(jù)用 = String
- 單線程操作字符串緩沖區(qū) 下操作大量數(shù)據(jù) = StringBuilder
- 多線程操作字符串緩沖區(qū) 下操作大量數(shù)據(jù) = StringBuffer
StringBuffer和StringBuilder區(qū)別
1、是否線程安全
- StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在于 StringBuilder 的方法不是線程安全的(不能同步訪問),StringBuffer是線程安全的。只是StringBuffer 中的方法大都采用了 synchronized 關(guān)鍵字進(jìn)行修飾,因此是線程安全的,而 StringBuilder 沒有這個修飾,可以被認(rèn)為是線程不安全的。
2、應(yīng)用場景
- 由于 StringBuilder 相較于 StringBuffer 有速度優(yōu)勢,所以多數(shù)情況下建議使用 StringBuilder 類。
- 然而在應(yīng)用程序要求線程安全的情況下,則必須使用 StringBuffer 類。 append方法與直接使用+串聯(lián)相比,減少常量池的浪費(fèi)。
6. 什么是內(nèi)部類?內(nèi)部類的作用
內(nèi)部類的定義
將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內(nèi)部類。
內(nèi)部類的作用:
成員內(nèi)部類 成員內(nèi)部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態(tài)成員)。 當(dāng)成員內(nèi)部類擁有和外部類同名的成員變量或者方法時,會發(fā)生隱藏現(xiàn)象,即默認(rèn)情況下訪問的是成員內(nèi)部類的成員。
局部內(nèi)部類 局部內(nèi)部類是定義在一個方法或者一個作用域里面的類,它和成員內(nèi)部類的區(qū)別在于局部內(nèi)部類的訪問僅限于方法內(nèi)或者該作用域內(nèi)。
匿名內(nèi)部類 匿名內(nèi)部類就是沒有名字的內(nèi)部類
靜態(tài)內(nèi)部類 指被聲明為static的內(nèi)部類,他可以不依賴內(nèi)部類而實(shí)例,而通常的內(nèi)部類需要實(shí)例化外部類,從而實(shí)例化。靜態(tài)內(nèi)部類不可以有與外部類有相同的類名。不能訪問外部類的普通成員變量,但是可以訪問靜態(tài)成員變量和靜態(tài)方法(包括私有類型) 一個 靜態(tài)內(nèi)部類去掉static 就是成員內(nèi)部類,他可以自由的引用外部類的屬性和方法,無論是靜態(tài)還是非靜態(tài)。但是不可以有靜態(tài)屬性和方法
(學(xué)習(xí)視頻推薦:java課程)
7. The difference between abstract classes and interfaces
- Abstract classes must be inherited by subclasses, and interfaces must be implemented by classes.
- Interfaces can only make method declarations, while abstract classes can make method declarations and method implementations.
- The variables defined in the interface can only be public static constants, and the variables in the abstract class are ordinary variables.
- Interface is the result of design, and abstract class is the result of refactoring.
- Abstract classes and interfaces are used to abstract specific objects, but interfaces have the highest abstraction level.
- Abstract classes can have specific methods and properties, while interfaces can only have abstract methods and immutable constants.
- Abstract classes are mainly used to abstract categories, and interfaces are mainly used to abstract functions.
8. The meaning of abstract class
Abstract class: If a class contains abstract methods, the class should be declared as an abstract class using the abstract keyword.
Meaning:
- Provides a public type for subclasses;
- encapsulates repeated content (member variables and methods) in subclasses ;
- defines an abstract method. Although subclasses have different implementations, the definition of this method is consistent.
9. Application scenarios of abstract classes and interfaces
1. Application scenarios of interfaces:
- Necessary specificity between classes interface, regardless of how it is implemented.
- Exists as an identifier that can implement a specific function, or it can be a pure identifier without any interface methods.
- It is necessary to treat a group of classes as a single class, and the caller only contacts this group of classes through the interface.
- Need to implement specific multiple functions, and these functions may have no connection at all.
2. Application occasions of abstract class (abstract.class):
In a word, when both a unified interface and instance variables or default methods are needed , you can use it. The most common ones are:
- defines a set of interfaces, but does not want to force each implementation class to implement all interfaces. You can use abstract.class to define a set of method bodies, or even empty method bodies, and then the subclass can choose the methods it is interested in to cover.
- In some cases, pure interfaces alone cannot satisfy the coordination between classes. Variables representing states in the class must also be used to distinguish different relationships. The intermediary role of abstract can satisfy this very well.
- Specifies a set of mutually coordinated methods, some of which are common, independent of state, and can be shared without the need for subclasses to implement them separately; while other methods require each subclass to implement it according to its own specific State to achieve specific functions
10. Can an abstract class have no methods and attributes?
The answer is: Yes
There can be no abstract methods in abstract classes, but those with abstract methods must be abstract classes. Therefore, there can be no abstract methods in abstract classes in Java. Note that even abstract classes without abstract methods and properties cannot be instantiated.
11. 接口的意義
- 定義接口的重要性:在Java編程,abstract class 和interface是支持抽象類定義的兩種機(jī)制。正是由于這兩種機(jī)制的存在,才使得Java成為面向?qū)ο蟮木幊陶Z言。
- 定義接口有利于代碼的規(guī)范:對于一個大型項(xiàng)目而言,架構(gòu)師往往會對一些主要的接口來進(jìn)行定義,或者清理一些沒有必要的接口。這樣做的目的一方面是為了給開發(fā)人員一個清晰的指示,告訴他們哪些業(yè)務(wù)需要實(shí)現(xiàn);同時也能防止由于開發(fā)人員隨意命名而導(dǎo)致的命名不清晰和代碼混亂,影響開發(fā)效率。
- 有利于對代碼進(jìn)行維護(hù):比如你要做一個畫板程序,其中里面有一個面板類,主要負(fù)責(zé)繪畫功能,然后你就這樣定義了這個類。可是在不久將來,你突然發(fā)現(xiàn)現(xiàn)有的類已經(jīng)不能夠滿足需要,然后你又要重新設(shè)計(jì)這個類,更糟糕是你可能要放棄這個類,那么其他地方可能有引用他,這樣修改起來很麻煩。如果你一開始定義一個接口,把繪制功能放在接口里,然后定義類時實(shí)現(xiàn)這個接口,然后你只要用這個接口去引用實(shí)現(xiàn)它的類就行了,以后要換的話只不過是引用另一個類而已,這樣就達(dá)到維護(hù)、拓展的方便性。
- 保證代碼的安全和嚴(yán)密:一個好的程序一定符合高內(nèi)聚低耦合的特征,那么實(shí)現(xiàn)低耦合,定義接口是一個很好的方法,能夠讓系統(tǒng)的功能較好地實(shí)現(xiàn),而不涉及任何具體的實(shí)現(xiàn)細(xì)節(jié)。這樣就比較安全、嚴(yán)密一些,這一思想一般在軟件開發(fā)中較為常見。
12. Java泛型中的extends和super理解
在平時看源碼的時候我們經(jīng)??吹椒盒?,且經(jīng)常會看到extends和super的使用,看過其他的文章里也有講到上界通配符和下屆通配符,總感覺講的不夠明白。這里備注一下,以免忘記。
- extends也成為上界通配符,就是指定上邊界。即泛型中的類必須為當(dāng)前類的子類或當(dāng)前類。
- super也稱為下屆通配符,就是指定下邊界。即泛型中的類必須為當(dāng)前類或者其父類。
這兩點(diǎn)不難理解,extends修飾的只能取,不能放,這是為什么呢? 先看一個列子:
public?class?Food?{} public?class?Fruit?extends?Food?{} public?class?Apple?extends?Fruit?{} public?class?Banana?extends?Fruit{} public?class?GenericTest?{ ????public?void?testExtends(List?extends?Fruit>?list){ ????????//報(bào)錯,extends為上界通配符,只能取值,不能放. ????????//因?yàn)镕ruit的子類不只有Apple還有Banana,這里不能確定具體的泛型到底是Apple還是Banana,所以放入任何一種類型都會報(bào)錯 ????????//list.add(new?Apple()); ????????//可以正常獲取 ????????Fruit?fruit?=?list.get(1); ????} ????public?void?testSuper(List?super?Fruit>?list){ ????????//super為下界通配符,可以存放元素,但是也只能存放當(dāng)前類或者子類的實(shí)例,以當(dāng)前的例子來講, ????????//無法確定Fruit的父類是否只有Food一個(Object是超級父類) ????????//因此放入Food的實(shí)例編譯不通過 ????????list.add(new?Apple()); //????????list.add(new?Food()); ????????Object?object?=?list.get(1); ????} }
在testExtends方法中,因?yàn)榉盒椭杏玫氖莈xtends,在向list中存放元素的時候,我們并不能確定List中的元素的具體類型,即可能是Apple也可能是Banana。因此調(diào)用add方法時,不論傳入new Apple()還是new Banana(),都會出現(xiàn)編譯錯誤。
理解了extends之后,再看super就很容易理解了,即我們不能確定testSuper方法的參數(shù)中的泛型是Fruit的哪個父類,因此在調(diào)用get方法時只能返回Object類型。結(jié)合extends可見,在獲取泛型元素時,使用extends獲取到的是泛型中的上邊界的類型(本例子中為Fruit),范圍更小。
總結(jié):在使用泛型時,存取元素時用super,獲取元素時,用extends。
13. 父類的靜態(tài)方法能否被子類重寫
不能,父類的靜態(tài)方法能夠被子類繼承,但是不能夠被子類重寫,即使子類中的靜態(tài)方法與父類中的靜態(tài)方法完全一樣,也是兩個完全不同的方法。
class?Fruit{ ????static?String?color?=?"五顏六色"; ????static?public?void?call()?{ ????????System.out.println("這是一個水果"); ????} } public?class?Banana?extends?Fruit{ ????static?String?color?=?"黃色"; ????static?public?void?call()?{ ????????System.out.println("這是一個香蕉"); ????} ????public?static?void?main(String[]?args)?{ ????????Fruit?fruit?=?new?Banana(); ????????System.out.println(fruit.color);????//五顏六色 ????????fruit.call();?????????//這是一個水果 ????} }
如代碼所示,如果能夠被重寫,則輸出的應(yīng)該是這是一個香蕉。與此類似的是,靜態(tài)變量也不能夠被重寫。如果想要調(diào)用父類的靜態(tài)方法,應(yīng)該使用類來調(diào)用。 那為什么會出現(xiàn)這種情況呢? 我們要從重寫的定義來說:
重寫指的是根據(jù)運(yùn)行時對象的類型來決定調(diào)用哪個方法,而不是根據(jù)編譯時的類型。
對于靜態(tài)方法和靜態(tài)變量來說,雖然在上述代碼中使用對象來進(jìn)行調(diào)用,但是底層上還是使用父類來調(diào)用的,靜態(tài)變量和靜態(tài)方法在編譯的時候就將其與類綁定在一起。既然它們在編譯的時候就決定了調(diào)用的方法、變量,那就和重寫沒有關(guān)系了。
靜態(tài)屬性和靜態(tài)方法是否可以被繼承
可以被繼承,如果子類中有相同的靜態(tài)方法和靜態(tài)變量,那么父類的方法以及變量就會被覆蓋。要想調(diào)用就就必須使用父類來調(diào)用。
class?Fruit{ ????static?String?color?=?"五顏六色"; ????static?String?xingzhuang?=?"奇形怪狀"; ????static?public?void?call()?{ ????????System.out.println("這是一個水果"); ????} ????static?public?void?test()?{ ????????System.out.println("這是沒有被子類覆蓋的方法"); ????} } public?class?Banana?extends?Fruit{ ????static?String?color?=?"黃色"; ????static?public?void?call()?{ ????????System.out.println("這是一個香蕉"); ????} ????public?static?void?main(String[]?args)?{ ????????Banana?banana?=?new?Banana();???? ????????banana.test();?????//這是沒有被子類覆蓋的方法 ????????banana.call();?????//調(diào)用Banana類中的call方法????這是一個香蕉 ????????Fruit.call();?????????//調(diào)用Fruit類中的方法?這是一個水果 ????????System.out.println(banana.xingzhuang?+?"?"?+?banana.color);???//奇形怪狀?黃色 ????} }
從上述代碼可以看出,子類中覆蓋了父類的靜態(tài)方法的話,調(diào)用的是子類的方法,這個時候要是還想調(diào)用父類的靜態(tài)方法,應(yīng)該是用父類直接調(diào)用。如果子類沒有覆蓋,則調(diào)用的是父類的方法。靜態(tài)變量與此相似。
14. The difference between threads and processes
- Definition: A process is a running activity of a program on a certain data collection; a thread is an execution path in a process. (A process can create multiple threads)
- Role aspect: In a system that supports the thread mechanism, the process is the unit of system resource allocation, and the thread is the unit of CPU scheduling.
- Resource sharing: Resources cannot be shared between processes, but threads share the address space and other resources of the process in which they are located. At the same time, the thread also has its own stack, stack pointer, program counter and other registers.
- In terms of independence: The process has its own independent address space, but the thread does not. The thread must depend on the process to exist.
- In terms of overhead. Process switching is expensive. Threads are relatively small. (As mentioned before, the introduction of threads is also due to cost considerations.)
You can read this article: juejin.im/post/684490…
15. The difference between final, finally, and finalize
- final is used to declare properties, methods and classes, which respectively means that properties are immutable, methods cannot be overridden, and classes cannot be inherited.
- finally is exception handling Part of the statement structure, indicating that it is always executed.
- finalize is a method of the Object class. This method of the recycled object will be called when the garbage collector is executed. This method can be overridden to provide other functions during garbage collection. Resource recycling, such as closing files, etc.
16. The difference between serialization Serializable and Parcelable
If Intent in Android wants to transfer class objects, it can be achieved in two ways.
Method 1: Serializable, the class to be passed implements the Serializable interface to pass the object, Method 2: Parcelable, the class to be transferred implements the Parcelable interface to transfer the object.
Serializable (comes with Java): Serializable means serialization, which means converting an object into a storable or transmittable state. Serialized objects can be transmitted over the network or stored locally. Serializable is a tagged interface, which means that Java can efficiently serialize this object without implementing methods.
Parcelable (Android-specific): The original design intention of Android's Parcelable is because Serializable is too slow (using reflection), in order to facilitate communication between different components in the program and between different Android programs (AIDL) Designed to efficiently transfer data that only exists in memory. The implementation principle of the Parcelable method is to decompose a complete object, and each part after decomposition is a data type supported by Intent, thus realizing the function of passing the object.
Efficiency and selection:
The performance of Parcelable is better than that of Serializable, because the latter frequently GCs during the reflection process, so it is recommended to use Parcelable when transferring data between memories, such as transferring data between activities. Serializable can persist data for easy storage, so choose Serializable when you need to save or transmit data over the network. Because Parcelable may be different in different versions of Android, it is not recommended to use Parcelable for data persistence. Parcelable cannot be used when data is to be stored on disk, because Parcelable cannot guarantee the persistence of data when the outside world changes. Although Serializable is less efficient, it is still recommended to use Serializable at this time.
When passing complex data types through intent, one of the two interfaces must be implemented first. The corresponding methods are getSerializableExtra() and getParcelableExtra().
17. Can static properties and static methods be inherited? Can it be rewritten? And why?
The static properties and methods of the parent class can be inherited by the subclass
cannot be overridden by the subclass : When the reference of the parent class points to the subclass When using an object to call a static method or static variable, the method or variable in the parent class is called. It is not overridden by subclasses.
Reason:
Because the static method has allocated memory since the program started running, which means it has been hard-coded. All objects that reference this method (either objects of the parent class or objects of the subclass) point to the same piece of data in memory, which is the static method.
If a static method with the same name is defined in a subclass, it will not be overridden. Instead, another static method in the memory should be allocated to the subclass, and there is no such thing as rewriting.
18 The design intention of static inner classes in .java
Inner classes
Inner classes are classes defined inside a class. Why are there inner classes?
We know that in Java, classes are single inheritance, and a class can only inherit another concrete class or abstract class (which can implement multiple interfaces). The purpose of this design is that in multiple inheritance, when there are duplicate attributes or methods in multiple parent classes, the call results of the subclass will be ambiguous, so single inheritance is used.
The reason for using inner classes is that each inner class can independently inherit an (interface) implementation, so whether the outer class has inherited an (interface) implementation, it has no effect on the inner class.
In our programming, sometimes there are some problems that are difficult to solve using interfaces. At this time, we can use the ability provided by internal classes to inherit multiple concrete or abstract classes to solve these programs. Design issues. It can be said that interfaces only solve part of the problem, and inner classes make the solution of multiple inheritance more complete.
Static inner classes
Before talking about static inner classes, first understand the member inner classes (non-static inner classes).
Member inner class
Member inner class is also the most common inner class. It is a member of the outer class, so it can have unlimited access to all the outer classes. Although the member attributes and methods are private, if the outer class wants to access the member attributes and methods of the inner class, it needs to access it through the inner class instance.
Two points should be noted in the member inner class:
There cannot be any static variables and methods in the member inner class;
-
The member inner class is attached to the outer class, so the inner class can only be created after the outer class is created first.
Static inner class
There is one biggest difference between static inner classes and non-static inner classes: non-static inner classes are compiled after they are compiled A reference is then implicitly held to the outside world in which it was created, but the static inner class does not.
The absence of this reference means:
Its creation does not need to depend on the peripheral class.
It cannot use non-static member variables and methods of any peripheral class.
The other two internal classes: local internal classes and anonymous internal classes
Local internal classes
Local internal classes are Nested within methods and scopes, the use of this class is mainly to apply and solve more complex problems. We want to create a class to assist our solutions, but by then we do not want this class to be publicly available, so we A local inner class is generated. The local inner class is compiled like the member inner class, but its scope changes. It can only be used in this method and attribute, and it will become invalid when the method and attribute are removed.
Anonymous inner classes
Anonymous inner classes have no access modifiers.
new Anonymous inner class, this class must exist first.
When the formal parameter of the method needs to be used by the anonymous inner class, then the formal parameter must be final.
Anonymous inner classes have no explicit constructor, and the compiler will automatically generate a constructor that references the outer class.
Related recommendations:Getting started with java
The above is the detailed content of Summary of 2020 new Java basic interview questions. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

There are three common methods to traverse Map in Java: 1. Use entrySet to obtain keys and values at the same time, which is suitable for most scenarios; 2. Use keySet or values to traverse keys or values respectively; 3. Use Java8's forEach to simplify the code structure. entrySet returns a Set set containing all key-value pairs, and each loop gets the Map.Entry object, suitable for frequent access to keys and values; if only keys or values are required, you can call keySet() or values() respectively, or you can get the value through map.get(key) when traversing the keys; Java 8 can use forEach((key,value)->

In Java, Comparable is used to define default sorting rules internally, and Comparator is used to define multiple sorting logic externally. 1.Comparable is an interface implemented by the class itself. It defines the natural order by rewriting the compareTo() method. It is suitable for classes with fixed and most commonly used sorting methods, such as String or Integer. 2. Comparator is an externally defined functional interface, implemented through the compare() method, suitable for situations where multiple sorting methods are required for the same class, the class source code cannot be modified, or the sorting logic is often changed. The difference between the two is that Comparable can only define a sorting logic and needs to modify the class itself, while Compar

To deal with character encoding problems in Java, the key is to clearly specify the encoding used at each step. 1. Always specify encoding when reading and writing text, use InputStreamReader and OutputStreamWriter and pass in an explicit character set to avoid relying on system default encoding. 2. Make sure both ends are consistent when processing strings on the network boundary, set the correct Content-Type header and explicitly specify the encoding with the library. 3. Use String.getBytes() and newString(byte[]) with caution, and always manually specify StandardCharsets.UTF_8 to avoid data corruption caused by platform differences. In short, by

JavaScript data types are divided into primitive types and reference types. Primitive types include string, number, boolean, null, undefined, and symbol. The values are immutable and copies are copied when assigning values, so they do not affect each other; reference types such as objects, arrays and functions store memory addresses, and variables pointing to the same object will affect each other. Typeof and instanceof can be used to determine types, but pay attention to the historical issues of typeofnull. Understanding these two types of differences can help write more stable and reliable code.

InJava,thestatickeywordmeansamemberbelongstotheclassitself,nottoinstances.Staticvariablesaresharedacrossallinstancesandaccessedwithoutobjectcreation,usefulforglobaltrackingorconstants.Staticmethodsoperateattheclasslevel,cannotaccessnon-staticmembers,

std::chrono is used in C to process time, including obtaining the current time, measuring execution time, operation time point and duration, and formatting analysis time. 1. Use std::chrono::system_clock::now() to obtain the current time, which can be converted into a readable string, but the system clock may not be monotonous; 2. Use std::chrono::steady_clock to measure the execution time to ensure monotony, and convert it into milliseconds, seconds and other units through duration_cast; 3. Time point (time_point) and duration (duration) can be interoperable, but attention should be paid to unit compatibility and clock epoch (epoch)

HashMap implements key-value pair storage through hash tables in Java, and its core lies in quickly positioning data locations. 1. First use the hashCode() method of the key to generate a hash value and convert it into an array index through bit operations; 2. Different objects may generate the same hash value, resulting in conflicts. At this time, the node is mounted in the form of a linked list. After JDK8, the linked list is too long (default length 8) and it will be converted to a red and black tree to improve efficiency; 3. When using a custom class as a key, the equals() and hashCode() methods must be rewritten; 4. HashMap dynamically expands capacity. When the number of elements exceeds the capacity and multiplies by the load factor (default 0.75), expand and rehash; 5. HashMap is not thread-safe, and Concu should be used in multithreaded

ReentrantLock provides more flexible thread control in Java than synchronized. 1. It supports non-blocking acquisition locks (tryLock()), lock acquisition with timeout (tryLock(longtimeout, TimeUnitunit)) and interruptible wait locks; 2. Allows fair locks to avoid thread hunger; 3. Supports multiple condition variables to achieve a more refined wait/notification mechanism; 4. Need to manually release the lock, unlock() must be called in finally blocks to avoid resource leakage; 5. It is suitable for scenarios that require advanced synchronization control, such as custom synchronization tools or complex concurrent structures, but synchro is still recommended for simple mutual exclusion requirements.
