Maison > Java > javaDidacticiel > le corps du texte

Résumé des points de connaissance de l'entrevue Java

高洛峰
Libérer: 2017-02-08 10:28:55
original
1445 Les gens l'ont consulté

1. Quels sont les types de données primitifs en Java, leurs tailles et les classes d'encapsulation correspondantes ?

(1) booléen

Le type de données booléen est soit vrai, soit faux. Ce type de données représente 1 bit d'information, mais sa taille n'est pas définie avec précision.

La "Spécification de la machine virtuelle Java" indique : "Bien que le type de données booléen soit défini, il n'en fournit qu'une prise en charge très limitée. Il n'y a pas de valeur booléenne dans les instructions de bytecode dédiées à la machine virtuelle Java et les valeurs booléennes exploitées par les expressions du langage Java sont remplacées par le type de données int dans la machine virtuelle Java après compilation, et le tableau booléen sera codé dans un tableau d'octets de la machine virtuelle Java. Chaque élément booléen occupe 8 bits. . De cette façon, nous pouvons conclure que le type booléen est de 4 octets lorsqu'il est utilisé seul et de 1 octet dans un tableau. Alors pourquoi la machine virtuelle utilise-t-elle int au lieu de boolean ? Pourquoi ne pas utiliser byte ou short ? Cela n'économiserait-il pas plus d'espace mémoire ? En fait, la raison d'utiliser int est que pour les processeurs 32 bits actuels, il est plus efficace d'échanger des données 32 bits à la fois.

En résumé, on peut savoir que : le document officiel ne donne pas de définition précise du type booléen. La "Java Virtual Machine Spécification" donne "4 octets lorsqu'il est utilisé seul, et 1 octet pour un tableau booléen. ." "La définition de " dépend du fait que l'implémentation de la machine virtuelle respecte les spécifications, donc 1 octet ou 4 octets sont possibles. Il s’agit en fait d’un compromis entre le temps et l’espace.

La classe d'encapsulation de type booléen est Boolean.

(2) octet——1 octet——Octet

(3) court——2 octets——Court

(4) int——4 octets—— Entier

(5) long——8 octets——Long

(6) float——4 octets——Float

(7) double——8 octets— — —Double

(8) char——2 octets——Caractère

2 Parlons de la différence entre « == » et « equals() ». .

"Penser en Java" dit : "Les opérateurs relationnels génèrent un résultat booléen et calculent la relation entre les valeurs des opérandes."

"==" détermine si les adresses mémoire de deux objets sont identiques et convient aux types de données primitifs et aux types d'énumération (leurs variables stockent la valeur elle-même, tandis que les variables de type référence stockent les références) ;equals est une méthode d'implémentation de la classe Object consiste à comparer les adresses mémoire. Nous pouvons remplacer cette méthode pour personnaliser le concept d'"égalité". Par exemple, String, Date et d'autres classes de la bibliothèque de classes ont réécrit cette méthode.

En résumé, pour les comparaisons d'égalité entre les types énumérés et les types de données primitifs, "==" doit être utilisé ; pour les comparaisons d'égalité entre les types de référence, la méthode equals doit être utilisée.

3. Quels sont les quatre types de références en Java et leurs scénarios d'application ?

Référence forte : généralement la référence renvoyée lorsque nous utilisons l'opérateur new pour créer un objet est une référence forte.

Référence douce : si un objet ne peut être atteint que via une référence douce, alors le l'objet est Il sera recyclé lorsque la mémoire est insuffisante et pourra être utilisé dans le cache d'images. Lorsque la mémoire est insuffisante, le système recyclera automatiquement le Bitmap qui n'est plus utilisé

Référence faible : Si un objet. n'est accessible que via une référence faible, alors il sera recyclé (Même si la mémoire est suffisante), il pourra également être utilisé dans le cache d'image. A ce moment, tant que le Bitmap n'est plus utilisé, il le sera. recyclé

Référence virtuelle : La référence virtuelle est la référence la plus "faible" en Java, et elle ne peut même pas être obtenue via elle. Le seul but d'un objet référencé est que lorsque l'objet vers lequel il pointe est recyclé, il sera être ajouté à la file d'attente de référence afin que nous puissions savoir quand l'objet vers lequel il pointe est détruit.

4. Quelles méthodes sont définies dans l'objet ?

clone(), equals(), hashCode(), toString(), notify(), notifyAll(), wait(), finalize(), getClass()

5. Quelle est la fonction de hashCode ?

Veuillez consulter les principes de base et la mise en œuvre des tables de hachage

6. Quelles sont les différences entre ArrayList, LinkedList et Vector ?

ArrayList : utilise en interne des tableaux pour stocker des éléments, prend en charge un accès aléatoire efficace et prend en charge le redimensionnement dynamique.

LinkedList : utilise en interne des listes chaînées pour stocker des éléments, prend en charge l'insertion/suppression rapide d'éléments, mais le fait ne prend pas en charge un accès aléatoire efficace

Vector : peut être considéré comme une version thread-safe d'ArrayList

7. Quelle est la différence entre String, StringBuilder et StringBuffer ?

String : une séquence de caractères immuable. Pour y ajouter de nouveaux caractères, vous devez créer un nouvel objet String

StringBuilder : une séquence de caractères mutable, qui prend en charge l'ajout de nouveaux caractères (. pas besoin de créer un nouvel objet)

StringBuffer : peut être considéré comme une version thread-safe de StringBuilder

8. File d'attente et pile.

Map : les types de données qui stockent les paires clé-valeur en Java implémentent tous cette interface, qui représente une "table de mappage". Les deux opérations principales prises en charge sont get (Object key) et put (K key, V value), qui sont utilisées respectivement pour obtenir la valeur correspondant à la clé et insérer la paire clé-valeur dans la table de mappage.

Set : Les éléments en double ne sont pas autorisés dans le type set qui implémente cette interface, représentant un "ensemble" au sens mathématique. Les opérations de base qu'il prend en charge sont add(E e), Remove(Object o) et contain(Object o), qui sont utilisées respectivement pour ajouter des éléments, supprimer des éléments et déterminer si un élément donné existe dans l'ensemble.

List : les types de listes dans le cadre de collection en Java implémentent tous cette interface, représentant une séquence ordonnée. Prend en charge get(int index), add(E e) et d'autres opérations.

File d'attente : l'interface de file d'attente dans le cadre de collection Java représente une file d'attente "premier entré, premier sorti". Prend en charge l'ajout (élément E), la suppression () et d'autres opérations.

Stack : le type de données représentant la pile dans le cadre de collection Java. La pile est une structure de données "dernier entré, premier sorti". Prend en charge push(E item), pop() et d'autres opérations.

Pour des instructions plus détaillées, veuillez vous référer à la documentation officielle. Les étudiants qui ne sont pas familiers avec les structures de données pertinentes peuvent se référer à « Introduction aux algorithmes » ou à d'autres livres connexes.

9. La différence entre HashMap et HashTable

HashTable est thread-safe, mais HashMap ne l'est pas

HashMap autorise les clés nulles et les valeurs nulles. Cependant,

n'est pas autorisé dans HashTable. Pour une analyse plus détaillée, veuillez vous référer à l'analyse approfondie de HashMap et HashTable

10 Le principe de mise en œuvre de HashMap.

En termes simples, l'implémentation sous-jacente de HashMap est une "table de hachage basée sur une fermeture éclair". Pour une analyse détaillée, veuillez vous référer à l'analyse approfondie de HashMap et HashTable

11 Le principe de mise en œuvre de ConcurrentHashMap

ConcurrentHashMap est un HashMap qui prend en charge la lecture et la lecture simultanées. écriture.Sa caractéristique est que lors de la lecture des données, aucun verrouillage n'est requis et la granularité du verrouillage peut être maintenue aussi petite que possible lors de l'écriture des données. Puisqu’il utilise un « stockage segmenté » en interne, il vous suffit de verrouiller le « segment » où se trouvent les données à écrire. Pour une analyse détaillée de l'implémentation sous-jacente de ConcurrentHashMap, veuillez vous référer à Java Concurrent Programming : Concurrent Container ConcurrentHashMap

12. Quelle est la différence entre TreeMap, LinkedHashMap et HashMap ?

L'implémentation sous-jacente de HashMap est une table de hachage, donc les éléments qui y sont stockés ne sont pas ordonnés.

L'implémentation sous-jacente de TreeMap est un arbre rouge-noir, donc les éléments qu'il contient sont ordonnés ; . Le tri est basé sur l'ordre naturel ou sur l'objet Comparator fourni lors de la création du TreeMap.

LinkedHashMap peut mémoriser l'ordre dans lequel les éléments sont insérés.

Pour une explication plus détaillée, veuillez vous référer aux différences entre HashMap, LinkedMap et TreeMap

13. Quelle est la différence entre Collection et Collections ?

Collection est l'interface de base du framework de collection Java ; Collections est une classe d'outils fournie par le framework de collection Java, qui contient un grand nombre de méthodes statiques pour exploiter ou renvoyer des collections.

Pour ceux qui ne sont pas familiers avec le framework de collection Java, veuillez vous référer au Framework de collection des points technologiques de base Java

14. if Le bloc d'instructions try contient une instruction « return » Le bloc d'instructions final sera-t-il exécuté ?

La réponse est oui. Il n'y a que deux situations dans lesquelles les instructions du bloc final ne seront pas exécutées :

La méthode System.exit() est appelée

La JVM "plante".

15. Hiérarchie des exceptions en Java

La hiérarchie des exceptions en Java est la suivante :

Résumé des points de connaissance de lentrevue Java

Nous pouvons voir que la classe Throwable est la classe de base dans la hiérarchie des exceptions. La classe Error représente les erreurs internes, qui échappent à notre contrôle ; Exception représente les exceptions, et RuntimeException et ses sous-classes sont des exceptions non vérifiées. Ces exceptions incluent ArrayIndexOutOfBoundsException, NullPointerException, etc. Nous devons éviter les exceptions non vérifiées via des jugements conditionnels et d'autres occurrences d'instructions. IOException et ses sous-classes sont des exceptions vérifiées. Le compilateur vérifiera si nous avons fourni des gestionnaires d'exceptions pour toutes les exceptions vérifiées qui peuvent être levées. Sinon, une erreur sera signalée. Pour les exceptions non contrôlées, nous n'avons pas besoin de les intercepter (bien sûr, Java nous permet également de les intercepter, mais ce que nous devrions faire est d'éviter l'apparition d'exceptions non contrôlées).

16. Trois caractéristiques et significations de Java orienté objet

Trois caractéristiques majeures : l'encapsulation, l'héritage et le polymorphisme. Pour une introduction détaillée, veuillez cliquer sur les trois principales caractéristiques de Java orienté objet

17 La signification et la différence entre Override et Overload

Override signifie "écrasement", qui est la réécriture par la sous-classe de la classe parent Redéfinition de la même méthode dans

Surcharge signifie "surcharge", c'est-à-dire définir une nouvelle méthode avec le même nom que la méthode définie mais une signature différente

18. La différence entre interface et classe abstraite

L'interface est une convention, et la classe qui implémente l'interface doit suivre cette classe abstraite est essentiellement une classe, et le coût d'utilisation de la classe abstraite est supérieur à celui de l'interface. La comparaison entre les interfaces et les classes abstraites est la suivante :

Les classes abstraites peuvent contenir des attributs, des méthodes (y compris des méthodes abstraites et des méthodes avec des implémentations spécifiques) et des constantes. Les interfaces ne peuvent contenir que des constantes et des déclarations de méthode.

Les méthodes et les variables membres des classes abstraites peuvent définir la visibilité (telle que publique, privée, etc.) tandis que les méthodes des interfaces ne peuvent être publiques (la valeur par défaut est publique).

Une sous-classe ne peut avoir qu'une seule classe parent (classe concrète ou classe abstraite) ; une interface peut hériter de plusieurs interfaces, et une classe peut également implémenter plusieurs interfaces.

Lorsqu'une sous-classe implémente une méthode abstraite dans la classe parent, la visibilité peut être supérieure ou égale à celle de la classe parent tandis que la visibilité de la méthode d'interface dans la classe d'implémentation d'interface ne peut être que la même ; comme celui de l'interface (publique).

19. La différence entre les classes internes statiques et les classes internes non statiques

Les classes internes statiques ne contiendront pas de références aux classes externes, tandis que les classes internes non statiques le feront. Contient implicitement une référence à la classe englobante.

Pour en savoir plus sur les classes internes, veuillez cliquer sur Classes internes des points technologiques de base Java

20 Le principe d'implémentation du polymorphisme en Java

. L'état dit de polymorphisme signifie que la référence de la classe parent pointe vers l'objet de la classe enfant. Lors de l'appel d'une méthode, l'implémentation de la classe enfant sera appelée à la place de l'implémentation de la classe parent. La clé de la mise en œuvre du polymorphisme réside dans la « liaison dynamique ». Pour une introduction détaillée, veuillez cliquer sur le mécanisme d'implémentation interne de la liaison dynamique Java

21 Décrivez brièvement les deux méthodes de création de nouveaux threads en Java

Hériter du fil. classe (en supposant des sous-classes pour MyThread) et réécrivez la méthode run(), puis créez un nouvel objet MyThread et appelez start() dessus pour démarrer un nouveau thread.

Implémentez l'interface Runnable (en supposant que la classe d'implémentation est MyRunnable), puis transmettez l'objet MyRunnable en tant que paramètre au constructeur Thread et appelez la méthode start() sur l'objet Thread obtenu.

22. Décrivez brièvement la méthode de synchronisation des threads en Java

volatile : le modèle de mémoire Java garantit que l'écriture dans la même variable volatile se produit avant de la lire

synchronisé : Vous pouvez verrouiller un bloc de code ou une méthode. L'endroit "verrouillé" est appelé la section critique. Le thread entrant dans la section critique obtiendra le moniteur de l'objet, afin que les autres tentatives d'entrée dans la section critique le soient. le fil dans la zone sera bloqué car il ne pourra pas obtenir le moniteur. Un thread bloqué en attendant qu'un autre thread libère un moniteur ne peut pas être interrompu.

ReentrantLock : Le thread essayant d'acquérir le verrou peut être interrompu et un paramètre de délai d'attente peut être défini.

Pour une introduction plus détaillée, veuillez cliquer sur les principaux points techniques de Java - Multithreading

23. Décrivez brièvement les types de verrous granulaires en Java

En Java, les classes, objets, méthodes ou blocs de code peuvent être verrouillés. Pour une introduction plus détaillée, veuillez cliquer sur Java Core Technology Points Multithreading

24. Donnez une solution au problème "producteur-consommateur"

Utilisez la file d'attente de blocage :

public class BlockingQueueTest {    private int size = 20;    private ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(size);     
    public static void main(String[] args)  {
        BlockingQueueTest test = new BlockingQueueTest();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();
         
        producer.start();
        consumer.start();
    }     
    class Consumer extends Thread{
        @Override        public void run() {             while(true){                try {                    //从阻塞队列中取出一个元素                    queue.take();
                    System.out.println("队列剩余" + queue.size() + "个元素");
                } catch (InterruptedException e) {
                   
                }
            }
        }
    }     
    class Producer extends Thread{         
        @Override        public void run() {            while (true) {                try {                    //向阻塞队列中插入一个元素
                    queue.put(1);
                    System.out.println("队列剩余空间:" + (size - queue.size()));
                } catch (InterruptedException e) {
               
                }
            }
        }
    }
}
Copier après la connexion

25. Le concept de conception et le rôle de ThreadLocal

Le rôle de ThreadLocal est de fournir des variables locales dans un thread, ce qui peut garantir que les variables ThreadLocal de chaque thread sont indépendantes lorsqu'elles sont accessibles dans un environnement multithread. En d’autres termes, la variable ThreadLocal de chaque thread est dédiée à elle-même et n’est pas accessible aux autres threads. ThreadLocal est le plus couramment utilisé dans le scénario suivant : il existe des accès simultanés à des objets non thread-safe dans un environnement multithread, et l'objet n'a pas besoin d'être partagé entre les threads, mais nous ne voulons pas le verrouiller. Dans ce cas, ThreadLocal peut être utilisé pour que chaque thread conserve une copie de cet objet.

Pour une analyse des principes de mise en œuvre de ThreadLocal, veuillez cliquer pour une analyse approfondie de ThreadLocal

26 L'architecture globale du package concurrent

Résumé des points de connaissance de lentrevue Java.

27. ArrayBlockingQueue, CountDownLatch Le rôle de la classe

CountDownLatch : Permet à un ensemble de threads d'attendre que le compteur atteigne 0. Scénario applicable : lorsqu'un ou plusieurs threads doivent attendre qu'un nombre spécifié d'événements se produisent avant de poursuivre l'exécution.

ArrayBlockingQueue : une file d'attente de blocage basée sur l'implémentation du tableau, qui doit spécifier la capacité lors de sa construction. Le thread actuel est bloqué lorsque vous essayez d'ajouter des éléments à une file d'attente pleine ou de supprimer des éléments d'une file d'attente vide. Grâce à la file d'attente de blocage, nous pouvons travailler dans le mode suivant : le thread de travail peut périodiquement mettre les résultats intermédiaires dans la file d'attente de blocage, et d'autres threads peuvent extraire les résultats intermédiaires et effectuer d'autres opérations. Si le thread de travail s'exécute lentement (avant d'avoir le temps d'insérer des éléments dans la file d'attente), les autres threads qui prennent des éléments de la file d'attente l'attendront (en essayant de prendre des éléments de la file d'attente vide et de bloquer si le thread de travail s'exécute rapidement) ; (Si vous essayez d'insérer un élément dans une file d'attente complète), il attendra que d'autres threads suppriment l'élément avant de continuer.

28. La différence entre wait() et sleep()

wait() : méthode d'instance définie dans la classe Object. L'appel de la méthode wait sur l'objet spécifié mettra le thread actuel dans un état d'attente (à condition que le thread actuel détienne le moniteur de l'objet à ce moment, le thread actuel libérera le moniteur de l'objet correspondant, de sorte que les autres). les threads auront la possibilité d’obtenir l’objet. Lorsque d'autres threads obtiennent le moniteur de cet objet et effectuent les opérations requises, ils peuvent appeler la méthode notify pour réveiller le thread qui est précédemment entré dans l'état d'attente.

sleep() : méthode statique de la classe Thread, qui est utilisée pour mettre le thread actuel en état de veille afin que les autres threads aient une chance de s'exécuter. Un thread qui se met en veille ne libère pas le verrou qu'il détient.

29. Utilisation et avantages du pool de threads

Avantages : Réalisez la réutilisation des threads et évitez les frais généraux liés à la création et à la destruction répétées de threads ; la gestion unifiée des threads peut réduire le nombre de threads simultanés, mais un trop grand nombre de threads ont tendance à perdre trop de temps sur le changement de contexte de thread et la synchronisation des threads.

Utilisation : Nous pouvons appeler une méthode constructeur de ThreadPoolExecutor pour créer nous-mêmes un pool de threads. Mais nous pouvons généralement utiliser la méthode de fabrique statique fournie par la classe Executors pour créer plus facilement un objet pool de threads. Après avoir créé l'objet pool de threads, nous pouvons appeler la méthode submit pour soumettre la tâche au pool de threads pour exécution ; une fois le pool de threads utilisé, nous devons nous rappeler d'appeler la méthode d'arrêt pour le fermer.

Pour une introduction détaillée au pool de threads et une analyse de ses principes de mise en œuvre, veuillez cliquer sur Compréhension approfondie du pool de threads de Java

Comparaison d'efficacité entre pour. -chacune et conventionnelle pour les boucles

Concernant cette question, regardons directement la réponse que nous a donnée "Effective Java" :

for-each能够让代码更加清晰,并且减少了出错的机会。下面的惯用代码适用于集合与数组类型:
 
for (Element e : elements) {
    doSomething(e);
}使用for-each循环与常规的for循环相比,并不存在性能损失,即使对数组进行迭代也是如此。实际上,在有些场合下它还能带来微小的性能提升,因为它只计算一次数组索引的上限。
Copier après la connexion

Décrivez brièvement la différence entre Java IO et Java IO. NIO

Java IO est orienté flux, ce qui signifie que nous devons lire un ou plusieurs octets du flux à la fois jusqu'à ce que tous les octets soient lus. NIO est orienté tampon, ce qui signifie que les données seront lues. lire dans un tampon, puis traiter les données dans le tampon en conséquence.

Java IO bloque les IO, tandis que NIO ne bloque pas les IO.

Il existe quelque chose appelé sélecteur dans Java NIO, qui vous permet d'enregistrer plusieurs canaux dans un sélecteur, puis d'utiliser un thread pour surveiller ces canaux : S'il y a quelque chose dans ces canaux Lorsque le canal est prêt à commencer la lecture ou opérations d'écriture, commencez à lire et à écrire le canal correspondant. En attendant qu'un canal devienne lisible/inscriptible, le thread demandant des opérations de lecture et d'écriture sur le canal peut faire autre chose.

Pour plus d'explications, veuillez cliquer sur Java NIO et IO

32 Le rôle et le principe de la réflexion

Le rôle de la réflexion est de manière générale, runtime Obtenez diverses informations de définition de la classe, telles que les propriétés et les méthodes définies. Le principe est d'obtenir diverses informations sur une classe à travers son objet classe.

Pour une introduction détaillée, veuillez vous référer à Reflection, le point technique principal de Java

33 Mécanisme générique en Java

Pour une introduction détaillée. au mécanisme générique, veuillez examiner directement les points techniques fondamentaux de Java : Génériques

34 Nouvelles fonctionnalités de Java 7 et Java 8

En voici deux très bonnes. résumés : Java 7 Nouvelles fonctionnalités Nouvelles fonctionnalités de Java 8

35. Modèles de conception courants

Les soi-disant « modèles de conception » ne sont que quelques techniques de conception de logiciels couramment utilisées dans la programmation orientée objet, et Après des tests pratiques, ces techniques de conception peuvent résoudre certains besoins dans leurs scénarios respectifs, elles sont donc devenues aujourd'hui des « modèles de conception » largement diffusés. En d’autres termes, c’est officiellement parce que des problèmes épineux survenaient dans certains scénarios que les modèles de conception correspondants sont nés. Cela étant dit, lorsque nous apprenons un certain modèle de conception, nous devons pleinement comprendre le contexte de sa création et les principales contradictions qu’il résout.

Les modèles de conception couramment utilisés peuvent être divisés en trois catégories suivantes :

Modèles créatifs : y compris les modèles d'usine (qui peuvent être divisés en modèles d'usine simples, modèles de méthodes d'usine et modèles d'usine abstraits ), modèle de constructeur, modèle singleton.

Mode structurel : y compris le mode adaptateur, le mode pont, le mode décoration, le mode apparence, le mode poids mouche et le mode proxy.

Modèles comportementaux : notamment le mode commande, le mode médiateur, le mode observateur, le mode état et le mode stratégie.

Pour une introduction détaillée de chaque mode, veuillez vous référer au modèle de conception illustré

36 Utilisation de base de JNI

À propos de JNI, voici. un bon article : JNI dans Android

37. La définition, les scénarios d'application et les principes du proxy dynamique

Pour le proxy dynamique, veuillez vous référer directement au proxy dynamique de Java points technologiques de base

38 Le concept de base et l'utilisation des annotations

Les annotations peuvent être considérées comme des « versions améliorées des commentaires », qui peuvent expliquer certaines choses au compilateur. et machine virtuelle.

Les annotations sont des codes qui décrivent le code Java. Elles peuvent être analysées par le compilateur, et les outils de traitement des annotations peuvent également analyser les annotations au moment de l'exécution. L'annotation elle-même est une information « passive » et elle n'a de sens que si elle est activement analysée.

En plus de transmettre des informations au compilateur/machine virtuelle, nous pouvons également utiliser des annotations pour générer du code « modèle ».

Est-ce suffisant ? Bien sûr, pas assez. Ce qui précède répertorie les questions courantes sur Java dans les entretiens, et la plupart d'entre elles sont également les points techniques fondamentaux du système technologique Java. La série de questions soulevées par ces questions nous indique un moyen d'améliorer notre propre système de connaissances. Le mieux est de continuer sur cette voie :)

Pour plus de résumés des points de connaissance des entretiens Java et des articles connexes, veuillez faire attention au site Web PHP chinois !

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!