Résumé des nouvelles questions d'entretien de base Java 2020
Oct 21, 2020 pm 04:51 PMLa différence entre ==, égal et hashCode en java
(plus de recommandations de questions d'entretien?: questions et réponses d'entretien Java)
1. ==
Les types de données en Java peuvent être divisés en deux catégories?:
Types de données de base, également appelés types de données primitifs. Pour comparer byte, short, char, int, long, float, double, boolean, utilisez le double signe égal (==) et comparez leurs valeurs.
Type de référence (classe, interface, tableau) Lorsqu'ils comparent en utilisant (==), ils comparent leurs adresses de stockage en mémoire. Par conséquent, à moins qu'il ne s'agisse du même nouvel objet, le résultat de leur comparaison est vrai, sinon le résultat de la comparaison est faux. Les objets sont placés sur le tas et la référence (adresse) de l'objet est stockée sur la pile. Regardez d'abord la carte mémoire et le code de la machine virtuelle?:
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)); ????} }
Le résultat est?:
false
true

s1 et s2 stockent respectivement les adresses des objets correspondants. Par conséquent, si s1== s2 est utilisé, les valeurs d'adresse des deux objets sont comparées (c'est-à-dire si les références sont les mêmes), ce qui est faux. Lors de l'appel dans le sens égal, la valeur dans l'adresse correspondante est comparée, la valeur est donc vraie. Ici, nous devons décrire equals() en détail.
2. Explication détaillée de la méthode equals()
La méthode equals() est utilisée pour déterminer si d'autres objets sont égaux à cet objet. Il est défini dans Object, donc tout objet a la méthode equals(). La différence est de savoir si la méthode est remplacée ou non.
Regardez d'abord le code source?:
public?boolean?equals(Object?obj)?{????return?(this?==?obj); }
évidemment, Object définit une comparaison des valeurs d'adresse de deux objets (c'est-à-dire comparer si les références sont les mêmes). Mais pourquoi l'appel d'equals() dans String ne compare-t-il pas l'adresse mais la valeur dans l'adresse de la mémoire tas?? Voici le point clé. Lorsque des classes d'encapsulation telles que String, Math, Integer, Double, etc. utilisent la méthode Equals(), elles ont déjà couvert la méthode Equals() de la classe d'objet. Jetez un ?il à la fonction equals() réécrite dans 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; }
Après la réécriture, il s'agit de la comparaison de contenu, et ce n'est plus la comparaison d'adresse précédente. Par analogie, les classes telles que Math, Integer, Double, etc. remplacent toutes la méthode equals() pour comparer les contenus. Bien entendu, les types de base effectuent des comparaisons de valeurs.
Il convient de noter que lorsque la méthode equals() est remplacée, hashCode() sera également remplacée. Selon l'implémentation de la méthode générale hashCode(), les objets égaux doivent avoir des codes de hachage égaux. Pourquoi en est-il ainsi ? Nous mentionnons ici brièvement le hashcode.
3. Une brève discussion sur hashcode()
Il s'agit évidemment de la différence entre ==, égal et hashCode en Java, mais pourquoi est-il soudainement lié à hashcode(). Vous devez être très déprimé, d'accord, laissez-moi vous donner un exemple simple et vous saurez pourquoi hashCode est impliqué lorsque == ou égal.
Par exemple?: Si vous souhaitez savoir si une collection contient un objet, comment devez-vous écrire le programme?? Si vous n'utilisez pas la méthode indexOf, parcourez simplement la collection et comparez si vous y pensez. Et s’il y avait 10 000 éléments dans la collection, ce serait fatiguant, non ? Par conséquent, afin d’améliorer l’efficacité, un algorithme de hachage a été créé. L'idée principale est de diviser la collection en plusieurs zones de stockage (peuvent être considérées comme des compartiments). Chaque objet peut calculer un code de hachage et peut être regroupé en fonction du code de hachage. un objet peut être regroupé selon le hash code. Son hash code peut être divisé en différentes zones de stockage (différentes zones).
Ainsi, lors de la comparaison d'éléments, le hashcode est en fait comparé en premier s'ils sont égaux, la méthode égale est comparée.
Regardez le diagramme du hashcode?:

Un objet a généralement une clé et une valeur, et sa valeur hashCode peut être calculée en fonction de la clé, il est ensuite stocké dans différentes zones de stockage en fonction de sa valeur hashCode, comme indiqué ci-dessus. Différentes zones peuvent stocker plusieurs valeurs car des conflits de hachage sont impliqués. Simple?: si le hashCode de deux objets différents est le même, ce phénomène est appelé conflit de hachage. En termes simples, cela signifie que le hashCode est le même mais que l'égalité est une valeur différente. Pour comparer 10 000 éléments, il n'est pas nécessaire de parcourir toute la collection. Il suffit de calculer le hashCode de la clé de l'objet que vous souhaitez rechercher, puis de trouver la zone de stockage correspondant au hashCode. La recherche est terminée.

大概可以知道,先通過hashcode來比較,如果hashcode相等,那么就用equals方法來比較兩個對象是否相等。再重寫了equals最好把hashCode也重寫。其實這是一條規(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變量必須實例化后才能使用,而int變量不需要
- Integer實際是對象的引用,當(dāng)new一個Integer時,實際上是生成一個指針指向此對象;而int則是直接存儲數(shù)據(jù)值
- Integer的默認值是null,int的默認值是0
延伸: 關(guān)于Integer和int的比較
- 由于Integer變量實際上是對一個Integer對象的引用,所以兩個通過new生成的Integer變量永遠是不相等的(因為new生成的是兩個對象,其內(nèi)存地址不同)。
Integer?i?=?new?Integer(100); Integer?j?=?new?Integer(100); System.out.print(i?==?j);?//false
- Integer變量和int變量比較時,只要兩個變量的值是向等的,則結(jié)果為true(因為包裝類Integer和基本數(shù)據(jù)類型int比較時,java會自動拆包裝為int,然后進行比較,實際上就變?yōu)閮蓚€int變量的比較)
Integer?i?=?new?Integer(100); int?j?=?100; System.out.print(i?==?j);?//true
- 非new生成的Integer變量和new Integer()生成的變量比較時,結(jié)果為false。(因為非new生成的Integer變量指向的是java常量池中的對象,而new Integer()生成的變量指向堆中新建的對象,兩者在內(nèi)存中的地址不同)
Integer?i?=?new?Integer(100); Integer?j?=?100; System.out.print(i?==?j);?//false
- 對于兩個非new生成的Integer對象,進行比較時,如果兩個變量的值在區(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ù),會進行緩存,Integer i = 127時,會將127進行緩存,下次再寫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)實意義理解:</p></li> </ol>
現(xiàn)實事物經(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)中成員的特點
- 多態(tài)成員變量:編譯運行看左邊
Fu f=new Zi();
System.out.println(f.num);//f是Fu中的值,只能取到父中的值
- 多態(tài)成員方法:編譯看左邊,運行看右邊
Fu f1=new Zi();
System.out.println(f1.show());//f1的門面類型是Fu,但實際類型是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)不需要面對子類類型時,通過提高擴展性,或者使用父類的功能就能完成相應(yīng)的操作。
-
向下轉(zhuǎn)型:一個已經(jīng)向上轉(zhuǎn)型的子類對象可以使用強制類型轉(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("認真授課"); ????} }
答案:吃水煮肉片 好好學(xué)習(xí)
例2:
請問題目運行結(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ā)生長度變化,是非常耗費內(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)鍵字進行修飾,因此是線程安全的,而 StringBuilder 沒有這個修飾,可以被認為是線程不安全的。
2、應(yīng)用場景
- 由于 StringBuilder 相較于 StringBuffer 有速度優(yōu)勢,所以多數(shù)情況下建議使用 StringBuilder 類。
- 然而在應(yīng)用程序要求線程安全的情況下,則必須使用 StringBuffer 類。 append方法與直接使用+串聯(lián)相比,減少常量池的浪費。
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)象,即默認情況下訪問的是成員內(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)部類而實例,而通常的內(nèi)部類需要實例化外部類,從而實例化。靜態(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. La différence entre les classes abstraites et les interfaces
- Les classes abstraites doivent être héritées par les sous-classes, et les interfaces doivent être implémentées par les classes.
- Les interfaces ne peuvent faire que des déclarations de méthodes, tandis que les classes abstraites peuvent faire des déclarations de méthodes et des implémentations de méthodes.
- Les variables définies dans l'interface ne peuvent être que des constantes statiques publiques, et les variables des classes abstraites sont des variables ordinaires.
- L'interface est le résultat de la conception, et la classe abstraite est le résultat d'une refactorisation.
- Les classes abstraites et les interfaces sont utilisées pour abstraire des objets spécifiques, mais les interfaces ont le plus haut niveau d'abstraction.
- Les classes abstraites peuvent avoir des méthodes et des propriétés spécifiques, tandis que les interfaces ne peuvent avoir que des méthodes abstraites et des constantes immuables.
- Les classes abstraites sont principalement utilisées pour abstraire des catégories, et les interfaces sont principalement utilisées pour abstraire des fonctions.
8. La signification de la classe abstraite
Classe abstraite?: Si une classe contient des méthodes abstraites, la classe doit être déclarée comme classe abstraite à l'aide du mot-clé abstract.
Signification?:
- Fournit un type public pour les sous-classes
- encapsule le contenu répété (variables membres et méthodes) dans les sous-classes ;
- définit une méthode abstraite. Bien que les sous-classes aient des implémentations différentes, la définition de cette méthode est cohérente.
9. Scénarios d'application des classes abstraites et des interfaces
1. Scénarios d'application des interfaces?:
- Il existe des exigences spécifiques entre les interfaces de classes, quelle que soit l'interface des classes. comment il est mis en ?uvre.
- existe comme un identifiant qui peut implémenter une fonction spécifique, ou il peut s'agir d'un pur identifiant sans aucune méthode d'interface.
- Il est nécessaire de traiter un groupe de classes comme une seule classe, et l'appelant ne contacte ce groupe de classes que via l'interface.
- Plusieurs fonctions spécifiques doivent être implémentées, et ces fonctions peuvent n'avoir aucun lien.
2. Occasions d'application de la classe abstraite (abstract.class) :
En un mot, lorsqu'à la fois une interface unifiée et des variables d'instance ou des méthodes par défaut sont nécessaires, vous pouvez l'utiliser . Les plus courants sont?:
- définit un ensemble d'interfaces, mais ne veut pas forcer chaque classe d'implémentation à implémenter toutes les interfaces. Vous pouvez utiliser abstract.class pour définir un ensemble de corps de méthode, ou même des corps de méthode vides, puis la sous-classe peut choisir les méthodes qu'elle souhaite couvrir.
- Dans certains cas, les interfaces pures ne peuvent à elles seules satisfaire la coordination entre les classes. Les variables représentant les états de la classe doivent également être utilisées pour distinguer différentes relations. Le r?le intermédiaire de l’abstrait peut très bien y répondre.
- spécifie un ensemble de méthodes mutuellement coordonnées, dont certaines sont communes, indépendantes de l'état et peuvent être partagées sans qu'il soit nécessaire que des sous-classes les implémentent séparément, tandis que d'autres méthodes nécessitent que chaque sous-classe l'implémente en fonction de ses caractéristiques?; propre état spécifique pour implémenter des fonctions spécifiques
10. Une classe abstraite peut-elle n'avoir ni méthodes ni attributs ?
La réponse est?: Oui
Il ne peut y avoir de méthodes abstraites dans les classes abstraites, mais celles qui ont des méthodes abstraites doivent être des classes abstraites. Par conséquent, il ne peut y avoir de méthodes abstraites dans les classes abstraites en Java. Notez que même les classes abstraites sans méthodes et propriétés abstraites ne peuvent pas être instanciées.
11. 接口的意義
- 定義接口的重要性:在Java編程,abstract class 和interface是支持抽象類定義的兩種機制。正是由于這兩種機制的存在,才使得Java成為面向?qū)ο蟮木幊陶Z言。
- 定義接口有利于代碼的規(guī)范:對于一個大型項目而言,架構(gòu)師往往會對一些主要的接口來進行定義,或者清理一些沒有必要的接口。這樣做的目的一方面是為了給開發(fā)人員一個清晰的指示,告訴他們哪些業(yè)務(wù)需要實現(xiàn);同時也能防止由于開發(fā)人員隨意命名而導(dǎo)致的命名不清晰和代碼混亂,影響開發(fā)效率。
- 有利于對代碼進行維護:比如你要做一個畫板程序,其中里面有一個面板類,主要負責(zé)繪畫功能,然后你就這樣定義了這個類??墒窃诓痪脤?,你突然發(fā)現(xiàn)現(xiàn)有的類已經(jīng)不能夠滿足需要,然后你又要重新設(shè)計這個類,更糟糕是你可能要放棄這個類,那么其他地方可能有引用他,這樣修改起來很麻煩。如果你一開始定義一個接口,把繪制功能放在接口里,然后定義類時實現(xiàn)這個接口,然后你只要用這個接口去引用實現(xiàn)它的類就行了,以后要換的話只不過是引用另一個類而已,這樣就達到維護、拓展的方便性。
- 保證代碼的安全和嚴密:一個好的程序一定符合高內(nèi)聚低耦合的特征,那么實現(xiàn)低耦合,定義接口是一個很好的方法,能夠讓系統(tǒng)的功能較好地實現(xiàn),而不涉及任何具體的實現(xiàn)細節(jié)。這樣就比較安全、嚴密一些,這一思想一般在軟件開發(fā)中較為常見。
12. Java泛型中的extends和super理解
在平時看源碼的時候我們經(jīng)??吹椒盒?,且經(jīng)常會看到extends和super的使用,看過其他的文章里也有講到上界通配符和下屆通配符,總感覺講的不夠明白。這里備注一下,以免忘記。
- extends也成為上界通配符,就是指定上邊界。即泛型中的類必須為當(dāng)前類的子類或當(dāng)前類。
- super也稱為下屆通配符,就是指定下邊界。即泛型中的類必須為當(dāng)前類或者其父類。
這兩點不難理解,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){ ????????//報錯,extends為上界通配符,只能取值,不能放. ????????//因為Fruit的子類不只有Apple還有Banana,這里不能確定具體的泛型到底是Apple還是Banana,所以放入任何一種類型都會報錯 ????????//list.add(new?Apple()); ????????//可以正常獲取 ????????Fruit?fruit?=?list.get(1); ????} ????public?void?testSuper(List?super?Fruit>?list){ ????????//super為下界通配符,可以存放元素,但是也只能存放當(dāng)前類或者子類的實例,以當(dāng)前的例子來講, ????????//無法確定Fruit的父類是否只有Food一個(Object是超級父類) ????????//因此放入Food的實例編譯不通過 ????????list.add(new?Apple()); //????????list.add(new?Food()); ????????Object?object?=?list.get(1); ????} }
在testExtends方法中,因為泛型中用的是extends,在向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ù)運行時對象的類型來決定調(diào)用哪個方法,而不是根據(jù)編譯時的類型。
對于靜態(tài)方法和靜態(tài)變量來說,雖然在上述代碼中使用對象來進行調(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. La différence entre les threads et les processus
- Définition?: Un processus est une activité en cours d'exécution d'un programme sur une certaine collection de données?; un thread est un chemin d'exécution dans un processus. (Un processus peut créer plusieurs threads)
- Aspect du r?le?: dans un système qui prend en charge le mécanisme des threads, le processus est l'unité d'allocation des ressources système et le thread est l'unité de planification du processeur.
- Partage des ressources?: les ressources ne peuvent pas être partagées entre les processus, mais les threads partagent l'espace d'adressage et les autres ressources du processus dans lequel ils se trouvent. Dans le même temps, le thread possède également sa propre pile, son pointeur de pile, son compteur de programme et d'autres registres.
- En termes d'indépendance?: le processus a son propre espace d'adressage indépendant, mais pas le thread. Le thread doit dépendre du processus pour exister.
- En termes de dépenses. La commutation de processus co?te cher. Les fils sont relativement petits. (Comme mentionné précédemment, l'introduction des fils de discussion est également due à des considérations de co?t.)
Vous pouvez lire cet article?: juejin.im/post/684490…
15. entre final, final et finalize
- final est utilisé pour déclarer des propriétés, des méthodes et des classes, ce qui signifie respectivement que les propriétés sont immuables, que les méthodes ne peuvent pas être remplacées et que les classes ne peuvent pas être héritées <.>finally est la gestion des exceptions Une partie de la structure de l'instruction, indiquant qu'elle est toujours exécutée.
- finalize est une méthode de la classe Object. Cette méthode de l'objet recyclé sera appelée lors de l'exécution du garbage collector. Cette méthode peut être remplacée pour fournir d'autres fonctions lors du recyclage des ressources, telles que la fermeture de fichiers, etc.
Méthode 1?:?Sérialisable, la classe à passer implémente l'interface Serialisable pour passer l'objet, Méthode 2 : Parcelable, la classe à transférer implémente l'interface Parcelable pour transférer l'objet.
Sérialisable (livré avec Java)?: Sérialisable signifie sérialisation, ce qui signifie convertir un objet en un état stockable ou transférable. Les objets sérialisés peuvent être transmis sur le réseau ou stockés localement. Serialisable est une interface balisée, ce qui signifie que Java peut sérialiser efficacement cet objet sans implémenter de méthodes.
Parcelable (exclusivement pour Android)?: L'intention de conception originale de Parcelable d'Android est que Serialisable est trop lent (en utilisant la réflexion), afin de faciliter la communication entre les différents composants du programme et entre différents programmes Android (AIDL) Con?us pour transférer efficacement des données qui n'existent qu'en mémoire. Le principe d'implémentation de la méthode Parcelable est de décomposer un objet complet, et chaque partie après décomposition est un type de données pris en charge par Intent, réalisant ainsi la fonction de passage de l'objet.
Efficacité et sélection?: Parcelable a de meilleures performances que Serialisable, car ce dernier est fréquemment GC pendant le processus de réflexion, il est donc recommandé d'utiliser Parcelable lors du transfert de données entre mémoires, comme le transfert de données entre les activités. Serialisable peut conserver les données pour un stockage facile, alors choisissez Serialisable lorsque vous devez enregistrer ou transmettre des données sur le réseau. étant donné que Parcelable peut être différent selon les versions d'Android, il n'est pas recommandé d'utiliser Parcelable pour la persistance des données. Parcelable ne peut pas être utilisé lorsque les données doivent être stockées sur disque, car Parcelable ne peut pas garantir la persistance des données lorsque le monde extérieur change. Bien que Serialisable soit moins efficace, il est toujours recommandé d'utiliser Serialisable pour le moment. Lors du passage de types de données complexes via intent, l'une des deux interfaces doit être implémentée en premier. Les méthodes correspondantes sont getSerializingExtra() et getParcelableExtra(). 17. Les propriétés statiques et les méthodes statiques peuvent-elles être héritées?? Peut-il être réécrit ? Et pourquoi ?Les propriétés et méthodes statiques de la classe parent peuvent être héritées par la sous-classe
ne peuvent pas être remplacées par la sous-classe ?: Lorsque la référence de la classe parent pointe vers la sous-classe Lorsque vous utilisez un objet pour appeler une méthode statique ou une variable statique, la méthode ou la variable de la classe parent est appelée. Il n'est pas remplacé par les sous-classes.
Raison?:
Parce que la méthode statique a alloué de la mémoire depuis le début de l'exécution du programme, ce qui signifie qu'elle a été codée en dur. Tous les objets qui font référence à cette méthode (soit les objets de la classe parent, soit les objets de la sous-classe) pointent vers la même donnée en mémoire, qui est la méthode statique. Si une méthode statique portant le même nom est définie dans une sous-classe, elle ne sera pas remplacée. Au lieu de cela, une autre méthode statique de la sous-classe doit être allouée en mémoire, et la substitution n'existe pas. 18. L'intention de conception des classes internes statiques en Java Classes internes Les classes internes sont des classes définies à l'intérieur d'une classe. Pourquoi y a-t-il des classes internes ? Nous savons qu'en Java, les classes sont à héritage unique et qu'une classe ne peut hériter qu'une autre classe concrète ou classe abstraite (qui peut implémenter plusieurs interfaces). Le but de cette conception est que dans l'héritage multiple, lorsqu'il y a des attributs ou des méthodes en double dans plusieurs classes parents, le résultat de l'appel de la sous-classe sera ambigu, donc un héritage unique est utilisé.La raison de l'utilisation des classes internes est que chaque classe interne peut hériter indépendamment d'une implémentation (de l'interface), donc si la classe externe a hérité d'une implémentation (de l'interface), cela n'a aucun effet sur la classe interne.
Dans notre programmation, il existe parfois des problèmes difficiles à résoudre à l'aide d'interfaces. à l'heure actuelle, nous pouvons utiliser la capacité fournie par les classes internes d'hériter de plusieurs classes concrètes ou abstraites pour résoudre ces problèmes de conception. . On peut dire que les interfaces ne résolvent qu'une partie du problème et que les classes internes rendent la solution de l'héritage multiple plus complète.
Classes internes statiques
Avant de parler de classes internes statiques, comprenons d'abord les classes internes membres (classes internes non statiques).
Classe interne membre
La classe interne membre est également la classe interne la plus courante. Elle est membre de la classe externe, elle peut donc avoir un accès illimité à tous. classes externes. Bien que les propriétés et méthodes des membres soient privées, si la classe externe souhaite accéder aux propriétés et méthodes des membres de la classe interne, elle doit y accéder via l'instance de classe interne.
Deux points à noter dans les classes internes membres?:
Il ne peut y avoir de variables ni de méthodes statiques dans les classes internes membres?;
-
La classe interne membre est attachée à la classe externe, donc la classe interne ne peut être créée qu'après la création préalable de la classe externe.
Classes internes statiques
Il existe une plus grande différence entre les classes internes statiques et les classes internes non statiques?: les classes internes non statiques sont compilées après la compilation, une référence est alors implicitement liée au monde extérieur dans lequel elle a été créée, mais pas la classe interne statique.
L'absence de cette référence signifie :
Sa création n'a pas besoin de dépendre de la classe environnante.
Il ne peut pas utiliser de variables membres non statiques et de méthodes d'aucune classe périphérique.
Les deux autres classes internes : les classes internes locales et les classes internes anonymes
Les classes internes locales
Les classes internes locales sont Nichée dans des méthodes et des portées, l'utilisation de cette classe est principalement destinée à appliquer et à résoudre des problèmes plus complexes. Nous souhaitons créer une classe pour faciliter nos solutions, mais à ce stade, nous ne voulons pas que cette classe soit accessible au public, nous A. La classe interne locale est générée. La classe interne locale est compilée de la même manière que la classe interne membre, mais sa portée a changé. Elle ne peut être utilisée que dans cette méthode et cet attribut, et elle deviendra invalide en dehors de la méthode et de l'attribut.
Classes internes anonymes
Les classes internes anonymes n'ont aucun modificateur d'accès.
nouvelle classe interne anonyme, cette classe doit exister en premier.
Lorsque le paramètre formel de la méthode doit être utilisé par la classe interne anonyme, alors le paramètre formel doit être final.
Les classes internes anonymes n'ont pas de constructeur explicite et le compilateur générera automatiquement un constructeur qui fait référence à la classe externe.
Recommandations associées?: Démarrer avec Java
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1
éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Pour gérer correctement les transactions JDBC, vous devez d'abord désactiver le mode de validation automatique, puis effectuer plusieurs opérations, et enfin vous engager ou randonner en fonction des résultats; 1. Appelez Conn.SetAutoCommit (false) pour démarrer la transaction; 2. Exécuter plusieurs opérations SQL, telles que l'insertion et la mise à jour; 3. Appelez Conn.Commit () Si toutes les opérations sont réussies, et appelez Conn.Rollback () Si une exception se produit pour garantir la cohérence des données; Dans le même temps, les ressources TRY-With doivent être utilisées pour gérer les ressources, gérer correctement les exceptions et cl?turer les connexions pour éviter la fuite de connexion; De plus, il est recommandé d'utiliser des pools de connexion et de définir des points de sauvegarde pour réaliser un retour en arrière partiel, et de maintenir les transactions aussi courtes que possible pour améliorer les performances.

Utilisez des classes dans le package Java.Time pour remplacer les anciennes classes de date et de calendrier; 2. Obtenez la date et l'heure actuelles via LocalDate, LocalDateTime et Localtime; 3. Créez une date et une heure spécifiques en utilisant la méthode OF (); 4. Utilisez la méthode plus / moins pour augmenter et diminuer le temps; 5. Utilisez ZonedDateTime et ZoneID pour traiter le fuseau horaire; 6. Format et cha?nes de date d'analyse via DateTimeFormatter; 7. Utilisez instantanément pour être compatible avec les anciens types de dates si nécessaire; Le traitement des dattes dans le Java moderne devrait donner la priorité à l'utilisation de Java.timeapi, qui fournit clairement, immuable et linéaire

Pré-formancetartuptimemoryusage, quarkusandmicronautleadduetocompile-timeprocessingandgraalvsupport, withquarkusofperforming lightbetterine scénarios.

HTTP Log Middleware dans GO peut enregistrer les méthodes de demande, les chemins de requête, la propriété intellectuelle du client et le temps qui prend du temps. 1. Utilisez http.handlerfunc pour envelopper le processeur, 2. Enregistrez l'heure de début et l'heure de fin avant et après l'appel Suivant.Servehttp, 3. Obtenez le vrai client IP via R.RemoteAddr et X-Forwared-For Headers, 4. Utilisez le log.printf aux journaux de demande de sortie, 5. L'exemple de code complet a été vérifié pour s'exécuter et convient au démarrage d'un projet petit et moyen. Les suggestions d'extension incluent la capture des codes d'état, la prise en charge des journaux JSON et le suivi des ID de demande.

La collecte des ordures de Java (GC) est un mécanisme qui gère automatiquement la mémoire, ce qui réduit le risque de fuite de mémoire en récupérant des objets inaccessibles. 1. GC juge l'accessibilité de l'objet de l'objet racine (tel que les variables de pile, les threads actifs, les champs statiques, etc.), et les objets inaccessibles sont marqués comme des ordures. 2. Sur la base de l'algorithme de compensation de marque, marquez tous les objets accessibles et effacez des objets non marqués. 3. Adopter une stratégie de collecte générationnelle: la nouvelle génération (Eden, S0, S1) exécute fréquemment MinorGC; Les personnes agées fonctionnent moins, mais prend plus de temps pour effectuer MajorGC; Metaspace Stores Metadata de classe. 4. JVM fournit une variété de périphériques GC: SerialGC convient aux petites applications; Le parallelGC améliore le débit; CMS réduit

Le choix du bon type HTMLinput peut améliorer la précision des données, améliorer l'expérience utilisateur et améliorer la convivialité. 1. Sélectionnez les types d'entrée correspondants en fonction du type de données, tels que le texte, le courrier électronique, le tel, le numéro et la date, qui peuvent vérifier automatiquement la somme de la somme et l'adaptation au clavier; 2. Utilisez HTML5 pour ajouter de nouveaux types tels que l'URL, la couleur, la plage et la recherche, qui peuvent fournir une méthode d'interaction plus intuitive; 3. Utilisez l'espace réservé et les attributs requis pour améliorer l'efficacité et la précision du remplissage des formulaires, mais il convient de noter que l'espace réservé ne peut pas remplacer l'étiquette.

GradleisthebetterChoiceFormostNewProjectsDuetOtsSuperiorflexibility, Performance et ModerNtoolingSupport.1.gradle’sgroovy / kotlindslismoreConcis

Le report est utilisé pour effectuer des opérations spécifiées avant le retour de la fonction, telles que les ressources de nettoyage; Les paramètres sont évalués immédiatement lorsqu'ils sont reportés et les fonctions sont exécutées dans l'ordre de la dernière entrée (LIFO); 1. Plusieurs éleveurs sont exécutés dans l'ordre inverse des déclarations; 2. Communément utilisé pour le nettoyage sécurisé tel que la fermeture des fichiers; 3. La valeur de retour nommée peut être modifiée; 4. Il sera exécuté même si la panique se produit, adaptée à la récupération; 5. éviter l'abus de report dans les boucles pour éviter la fuite des ressources; Une utilisation correcte peut améliorer la sécurité et la lisibilité du code.
