Maison >Java >JavaQuestions d'entretien >Questions d'entretien Java courantes (avec réponses)

Questions d'entretien Java courantes (avec réponses)

(*-*)浩
(*-*)浩original
2019-11-26 15:02:512555parcourir

Questions d'entretien Java courantes (avec réponses)

Comment implémenter une file d'attente à l'aide d'un tableau ?

Lors de l'utilisation de tableaux pour implémenter des files d'attente, nous devons faire attention au phénomène de débordement. Dans ce cas, nous pouvons utiliser la méthode de bouclage des tableaux pour résoudre le problème, c'est-à-dire connecter les extrémités du. tableaux. Utilisez le pointeur avant pour pointer vers la première position de la file d'attente et le pointeur arrière pour pointer vers la dernière position de la file d'attente. (Étude recommandée : Questions d'entretien courantes Java)

Lorsqu'une classe interne accède à une variable locale, pourquoi la variable doit-elle être modifiée avec final ?

Parce que le cycle de vie est différent. Les variables locales seront détruites une fois la méthode terminée, mais l'objet de la classe interne ne sera pas nécessairement détruit. Cela amènera la classe interne à référencer une variable qui n'existe pas.

Ainsi, le compilateur générera une copie de la variable locale dans la classe interne. Le cycle de vie de cette copie est le même que celui de l'objet de classe interne, donc les problèmes ci-dessus ne se produiront pas.

Mais cela conduit au problème que si l'une des variables est modifiée, les valeurs des deux variables peuvent être différentes. Afin de résoudre ce problème, le compilateur exige que les variables locales soient modifiées définitivement pour garantir que les deux variables ont la même valeur.

Après JDK8, le compilateur n'exige pas que les variables locales accessibles par les classes internes soient modifiées définitivement, mais les valeurs des variables locales ne peuvent pas être modifiées (ni dans les méthodes ni dans les classes internes), sinon une erreur de compilation sera signalé. En utilisant javap pour afficher le bytecode compilé, vous pouvez constater que le compilateur a ajouté final.

long s = 499999999 * 499999999 Dans le code ci-dessus, quelle est la valeur de s ?

Selon les résultats du calcul du code, la valeur de s devrait être -1371654655 En effet, le calcul de la valeur de droite en Java est par défaut le type int.

Les classes internes non statiques peuvent-elles définir des méthodes statiques ?

public class OuterClass{
    private static float f = 1.0f;

    class InnerClass{
        public static float func(){return f;}
    }
}

Le code ci-dessus provoquera une erreur de compilation car seules les classes internes statiques peuvent définir des méthodes statiques.

Quelle est la différence entre Verrouiller et Synchronisé ?

1. 使用方法的区别
- **Synchronized**:在需要同步的对象中加入此控制,`synchronized`可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
- **Lock**:需要显示指定起始位置和终止位置。一般使用`ReentrantLock`类做为锁,多个线程中必须要使用一个`ReentrantLock`类做为对象才能保证锁的生效。且在加锁和解锁处需要通过`lock()`和`unlock()`显示指出。所以一般会在`finally`块中写`unlock()`以防死锁。
2. 性能的区别
`synchronized`是托管给JVM执行的,而`lock`是java写的控制锁的代码。在Java1.5中,`synchronize`是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用Java提供的Lock对象,性能更高一些。但是到了Java1.6,发生了变化。`synchronize`在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上`synchronize`的性能并不比Lock差。
  - **Synchronized**:采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着 **其他线程只能依靠阻塞来等待线程释放锁**。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
  - **Lock**:用的是乐观锁方式。所谓乐观锁就是,**每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止**。乐观锁实现的机制就是`CAS`操作。我们可以进一步研究`ReentrantLock`的源代码,会发现其中比较重要的获得锁的一个方法是`compareAndSetState`。这里其实就是调用的CPU提供的特殊指令。
3. `ReentrantLock`:具有更好的可伸缩性:比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。

Comment une variable flottante se compare-t-elle à 0 ?

Il existe des types folat et des types doubles. La possibilité que ces types décimaux soient directement égaux à 0 lorsqu'ils s'approchent de 0 est très faible. Généralement, ils s'approchent de 0 à l'infini, donc = ne peut pas être utilisé = pour juger. Il doit être jugé par |x-0|

//用程序表示就是

fabs(x) < 0.00001f

Comment créer une nouvelle classe interne non statique ?

La classe interne doit être Outer.Inner a lorsqu'elle est déclarée, tout comme int a. Quant à la classe interne statique et à la classe interne non statique new, il y a une petite différence :

Outer.Inner a = new Outer().new Inner() (non statique, il doit y avoir un objet Outer avant que la nouvelle classe interne puisse être créée)

Outer.Inner a = new Outer.Inner( ) (classe interne statique)

Les règles de dénomination des identifiants Java

peuvent contenir : des lettres, des chiffres, $, _ (trait de soulignement), ne peuvent pas commencer par un chiffre et ne peuvent pas être des mots-clés Java ou des mots réservés.

Quels modèles de conception connaissez-vous utilisés dans le JDK ?

Mode de décoration : java.io

Mode Singleton : Classe d'exécution

Mode usine simple : méthode Integer.valueOf

Mode Flyweight : String pool constant, Integer.valueOf(int i), Character.valueOf(char c)

Mode itérateur : itérateur

Mode chaîne de responsabilité : modèle de délégation parent de ClassLoader

Interpréteur mode : Expression régulière java.util.regex.Pattern

Comment ConcurrentHashMap garantit la sécurité des threads

JDK 1.7 et antérieurs :

ConcurrentHashMap permet plusieurs opérations de modification à effectuer simultanément. La clé est l’utilisation de la technologie de séparation des serrures. Il utilise plusieurs verrous pour contrôler les modifications apportées aux différentes parties de la table de hachage. ConcurrentHashMap utilise des segments en interne pour représenter ces différentes parties. Chaque segment est en fait une petite table de hachage et possède ses propres verrous. Plusieurs opérations de modification peuvent avoir lieu simultanément à condition qu'elles se produisent sur des segments différents.

JDK 1.8 :

Bien que Segment soit conservé, ses attributs ont été simplifiés juste pour être compatible avec les anciennes versions.

Utilisez l'algorithme CAS lors de l'insertion : unsafe.compareAndSwapInt(this, valueOffset, expect, update). CAS (Compare And Swap) signifie que si la valeur contenue dans la position valueOffset est la même que la valeur attendue, mettez à jour la valeur de la position valueOffset pour mettre à jour et renvoyer true, sinon elle ne sera pas mise à jour et ne renverra pas false. La clé ou la valeur ne peut pas être nulle lors de l'insertion

C'est similaire au HashMap de Java8. La couche inférieure est toujours constituée d'un arbre de liste chaînée « tableau » rouge-noir

Le sous-jacent ; la structure stocke les objets TreeBin, et pas un objet TreeNode

CAS est un algorithme sans verrouillage bien connu, donc ConcurrentHashMap n'a-t-il pas de verrou ? Bien sûr que non, lorsque la valeur de hachage est la même que celle du nœud principal de la liste chaînée, elle sera toujours synchronisée et verrouillée, et la liste chaînée sera verrouillée.

La différence entre Thread.sleep() & Thread.yield()&Thread.wait()

sleep() et rendement() libéreront le processeur.

sleep() peut donner aux threads avec une faible priorité une chance de s'exécuter. Bien sûr, il peut également donner aux threads avec la même priorité et une priorité élevée une chance de s'exécuter. rendement() ne peut donner qu'aux threads avec la même priorité ; priorité une chance d'exécution. Il y a une chance d'exécution.

Thread.sleep et Thread.yield() ne modifieront pas le comportement du verrouillage. Si le thread actuel possède le verrou, alors Thread.sleep ne laissera pas le thread libérer le verrou. Si cela vous aide à vous en souvenir, vous pouvez simplement penser que les méthodes liées au verrouillage sont définies dans la classe Object, donc appeler Thread.sleep n'affectera pas le comportement lié au verrouillage.

Thread.sleep et Object.wait suspendront le thread actuel Pour les ressources CPU, quel que soit le thread suspendu, cela signifie qu'il n'a plus besoin de temps d'exécution CPU. Le système d'exploitation allouera du temps d'exécution aux autres threads. La différence est qu'après avoir appelé wait, d'autres threads doivent exécuter notify/notifyAll pour récupérer le temps d'exécution du CPU.

Quelle est la différence entre arraylist et linkedlist ?

ArrayList et LinkedList implémentent l'interface List, mais il existe quelques différences entre eux.

(1) ArrayList est une structure de données basée sur un index pris en charge par Array, elle fournit donc un accès aléatoire aux éléments

(2) Par rapport à ArrayList, l'insertion, l'ajout et la suppression d'un élément seront être plus rapide

(3) LinkedList consomme plus de mémoire que ArrayList car chaque nœud de LinkedList stocke la référence des nœuds précédents et suivants

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn