Cet article organise principalement des questions d'entrevue Java communes pour votre référence. Le contenu spécifique est le suivant
1. La différence entre le sommeil et l'attente en Java
① Ces deux méthodes proviennent de classes différentes, le sommeil provient de la classe de threads et l'attente vient de la classe d'objets.
Le sommeil est une méthode de classe de classe statique. Celui qui l'appelle s'endort. Même si la méthode de sommeil de B est appelée dans le fil A, elle va encore dormir. Pour faire dormir le fil B, vous devez appeler le sommeil dans le code de b.
② Lock: La chose la plus importante est que la méthode de sommeil ne libère pas le verrou, tandis que la méthode d'attente libère le verrou, afin que d'autres threads puissent utiliser des blocs ou des méthodes de contrôle synchrones.
Le sommeil ne transfère pas les ressources du système; L'attente est d'entrer dans le pool d'attente de threads pour attendre, transférer les ressources du système, et d'autres threads peuvent occuper le CPU. Généralement, l'attente n'ajoutera pas de délai, car si les ressources d'exécution du thread d'attente sont insuffisantes, il sera inutile de se retirer. Vous devez attendre que d'autres threads appellent Notify / Notifyall pour réveiller tous les threads de la piscine d'attente avant d'entrer dans la file d'attente Ready et d'attendre le système d'exploitation pour allouer les ressources système. Le sommeil (millisecondes) peut être spécifié pour le réveiller automatiquement. Si le temps est inférieur au temps, vous ne pouvez appeler Interrupt () que pour forcer l'interruption.
La fonction de Thread.Sleep (0) est de "déclencher le système d'exploitation pour récompéter une fois de plus CPU".
③ Portée d'utilisation: attendre, notifier et notifier que toute ne peut être utilisée que dans les méthodes de contrôle de synchronisation ou les blocs de contrôle de synchronisation, tandis que le sommeil peut être utilisé n'importe où.
synchronisé (x) {x.notify () // ou attend ()}2. La différence entre le hashmap et le hashtable en Java
① Raisons historiques: Hashable est donné à l'ancienne classe dictonaire. Hashmap est une implémentation de l'interface MAP introduite par Java 1.2.
② Hashmap permet des paires de valeurs de clé vides, tandis que le hashtable ne fait pas
③ Synchronisation de la hachage, tandis que Hashmap asynchrone est plus efficace que le hashtable
3. Veuillez décrire brièvement la différence entre lancer et lancer des exceptions
① Throw représente une action, ce qui signifie qu'une exception est lancée; Les lancers représentent un état, ce qui signifie que la méthode peut avoir une exception lancée ② Throw est utilisée dans l'implémentation de la méthode, tandis que les lancers sont utilisés dans la déclaration de la méthode ③ Throw ne peut être utilisé que pour lancer une exception, tandis que les lancers peuvent lancer plusieurs exceptions
4. La différence entre le débordement de la mémoire et les fuites de mémoire
La mémoire déborde de la mémoire fait référence au fait que lorsqu'un programme s'applique à la mémoire, il n'y a pas d'espace mémoire suffisant à utiliser et hors de la mémoire apparaît; Par exemple, si un entier est appliqué mais qu'il peut économiser longtemps, c'est un débordement de mémoire.
La fuite de mémoire de la mémoire La fuite de mémoire fait référence à l'incapacité du programme à libérer l'espace mémoire qui a été appliqué après avoir postulé pour la mémoire. Le préjudice d'une fuite de mémoire peut être ignoré, mais les conséquences de l'accumulation de fuite de mémoire sont très graves. Peu importe la quantité de mémoire, elle sera occupée tôt ou tard.
La fuite de mémoire mènera finalement à la mémoire!
Le débordement de la mémoire signifie que la mémoire dont vous avez besoin pour allouer dépasse ce que le système peut vous donner et que le système ne peut pas répondre aux besoins, donc un débordement se produit.
Les fuites de mémoire sont lorsque vous appliquez au système pour allouer la mémoire pour une utilisation (nouveau), mais après utilisation, il ne revient pas (supprimer). En conséquence, vous ne pouvez plus accéder à la mémoire pour laquelle vous avez postulé (peut-être que vous avez perdu son adresse), et le système ne peut plus l'allouer au programme requis. Si vous utilisez toutes les méthodes pour remplir une plaque, vous ne pouvez contenir que 4 fruits. Si vous en remplissez 5, vous tomberez au sol et vous ne pouvez pas le manger. C'est un débordement! Par exemple, si la pile est pleine, elle provoquera inévitablement un débordement d'espace lorsque la pile est pleine, ce qui est appelé débordement. Si la pile est vide, elle provoquera également un débordement d'espace lorsque la pile est vide, ce qui est appelé sous-écoulement. Cela signifie que la mémoire allouée n'est pas suffisante pour baisser la séquence des éléments de données, qui est appelé débordement de mémoire.
Classification Dans la façon dont cela se produit, les fuites de mémoire peuvent être divisées en 4 catégories:
① fuites de mémoire fréquentes. Le code qui se produit avec une fuite de mémoire sera exécuté plusieurs fois, et chaque fois qu'il est exécuté, il entraînera une fuite de mémoire.
② fuite de mémoire occasionnelle. Le code qui se produit avec des fuites de mémoire ne se produira que dans certains environnements ou opérations spécifiques. Les réguliers et occasionnels sont relatifs. Pour un environnement spécifique, l'occasion peut devenir fréquente. Par conséquent, l'environnement de test et les méthodes de test sont cruciaux pour détecter les fuites de mémoire.
③ Fuite de mémoire ponctuelle. Le code qui se produit avec une fuite de mémoire ne sera exécuté qu'une seule fois, ou en raison de défauts algorithmiques, il n'y aura toujours qu'une seule fuite de mémoire. Par exemple, la mémoire est allouée dans le constructeur de la classe, mais la mémoire n'est pas libérée dans le destructeur, donc les fuites de mémoire ne se produisent qu'une seule fois.
④ fuite de mémoire implicite. Le programme alloue en continu la mémoire pendant le fonctionnement, mais ne publie pas la mémoire avant sa fin. À strictement parler, il n'y a pas de fuite de mémoire ici parce que le programme libère finalement toute la mémoire demandée. Mais pour un programme de serveur, il faut plusieurs jours, des semaines ou même des mois à s'exécuter, et ne pas libérer de la mémoire à temps peut également conduire à la fin de toute la mémoire dans le système. Ainsi, nous appelons ce type de fuite de mémoire une fuite de mémoire implicite.
Du point de vue des utilisateurs utilisant des programmes, les fuites de mémoire elles-mêmes ne causeront aucun mal. En tant qu'utilisateur ordinaire, vous ne pouvez pas du tout ressentir l'existence de fuites de mémoire. Ce qui est vraiment nocif, c'est l'accumulation de fuites de mémoire, qui finira par consommer toute la mémoire du système. De ce point de vue, les fuites de mémoire ponctuelle ne sont pas nocives car elles ne s'accumulent pas, tandis que les fuites de mémoire implicites sont très nocives car elles sont plus difficiles à détecter que les fuites de mémoire fréquentes et occasionnelles.
5. La différence entre String, StringBuffer et StringBuilder
①variable et immuable
La classe de chaîne utilise un tableau de caractères pour enregistrer les chaînes, comme suit: Parce qu'il existe un modificateur "final", vous pouvez savoir que les objets de chaîne sont immuables.
Valeur charbon finale privée [];
StringBuilder et StringBuffer sont hérités de la classe AbstractStringBuilder. Dans AbstractStringBuilder, les tableaux de caractères sont utilisés pour enregistrer les chaînes. Comme suit, on peut voir que les deux objets sont mutables.
valeur char [];
② Est-ce multi-thread et sûr
Les objets en chaîne sont immuables, ils peuvent donc être compris comme des constantes, qui sont évidemment en file d'attente.
AbstractStringBuilder est une classe de parents publics de StringBuilder et StringBuffer, qui définit certaines opérations de base de chaînes, telles que la capitalisation, la capacité d'agrandissement, l'ajout, l'insertion, l'indexé et d'autres méthodes publiques.
StringBuffer a un verrou de synchronisation sur la méthode ou un verrou de synchronisation sur la méthode appelée, il est donc un thread-safe. Voir le code source suivant:
public synchronisé stringbuffer reverser () {super.reverse (); retourner ceci; } public int indexof (string str) {return indexof (str, 0); // Il y a une méthode publique Int Indexof (String Str, int FromIndex)} StringBuilder n'ajoute pas les verrous de synchronisation à la méthode, il est donc non-thread-safe.
③StringBuilder et StringBuffer en commun
StringBuilder et StringBuffer ont des classes de parents publiques AbstractStringBuilder (classe abstraite).
L'une des différences entre les classes abstraites et les interfaces est que certaines méthodes publiques de sous-classes peuvent être définies dans les classes abstraites. Les sous-classes doivent seulement ajouter de nouvelles fonctions et n'ont pas besoin de répéter les méthodes existantes; tandis que les interfaces ne définissent que des méthodes et des constantes.
Les méthodes de StringBuilder et StringBuffer appellent des méthodes publiques dans AbstractStringBuilder, comme Super.Apend (...). C'est juste que StringBuffer ajoutera un mot-clé synchronisé à la méthode et effectuera une synchronisation.
Enfin, si le programme n'est pas multithread, l'utilisation de StringBuilder est plus efficace que StringBuffer.
6. La différence entre les tableaux et les listes liées
Les deux appartiennent à une structure de données
À partir de la structure logique:
① Le tableau doit définir une longueur fixe (nombre d'éléments) à l'avance et ne peut pas s'adapter à l'augmentation dynamique et à la diminution des données. Lorsque les données augmentent, le nombre d'éléments peut dépasser le défini à l'origine; Lorsque les données diminuent, les déchets de mémoire seront causés; Le tableau peut être directement accessible en fonction de l'indice.
② La liste liée est stockée dynamiquement et allouée, qui peut s'adapter à l'augmentation et à la diminution dynamiques des données, et peut facilement insérer et supprimer les éléments de données. (Lors de l'insertion et de la suppression des éléments de données dans le tableau, vous devez déplacer d'autres éléments de données, ce qui est très lourd) La liste liée doit trouver l'élément suivant en fonction du pointeur suivant.
À partir du stockage de la mémoire:
① Les tableaux (statiques) alloueraient l'espace de la pile, ce qui est pratique et rapide pour les programmeurs, mais a peu de liberté.
② La liste liée alloue l'espace du tas, qui a beaucoup de liberté mais est plus difficile à postuler à la gestion.
D'après la comparaison ci-dessus, nous pouvons voir que si vous avez besoin d'accéder rapidement aux données et d'insérer et de supprimer rarement ou non des éléments, vous devez utiliser un tableau; Au contraire, si vous devez insérer et supprimer fréquemment des éléments, vous devez utiliser une structure de données de liste liée.
7. La différence entre ArrayList et LinkedList
①ArrayList implémente une structure de données basée sur des tableaux dynamiques, et LinkedList est basé sur une structure de données basée sur une liste liée.
② Pour un accès aléatoire pour obtenir et set, ArrayList est mieux que LinkedList car LinkedList doit déplacer le pointeur.
③ Pour les opérations d'addition et de suppression ajouter et supprimer, LinedList a un avantage relativement car car ArrayList doit déplacer des données.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.