Der folgende Inhalt ist verantwortungsbewusste Fragen und Antworten, die nach dem ursprünglichen Java -Interview -Frage -Set und den Antworten vollständig überarbeitet wurden. Es gibt viele doppelte Fragen und wertvolle Fragen in den ursprünglichen Fragen, und viele Referenzantworten sind ebenfalls falsch. Der modifizierte Java-Interview-Frage-Set bezieht sich auf die neueste Version von JDK, beseitigt nutzlose Inhalte wie EJB 2.x und ergänzt die Datenstruktur und die Algorithmus-bezogenen Fragen, klassische Interviewprogrammierfragen, eine große technische Architektur der großen Website, das Betriebssystem, die Datenbank, Softwaretests, Designmuster, UML und andere Inhalte. Gleichzeitig wurden viele Wissenspunkte tief analysiert, wie das Design der Hashcode -Methode, der Haufen und die Erzeugung der Müllsammlung, die neue gleichzeitige Programmierung von Java, NIO.2 usw. Ich glaube, es wird für Java -Programmierer, die sich vorbereiten, einen gewissen Vorteil sein wird.
Java Programmer Interview Fragen festgelegt (1-50)
1. Java -Grundlagen
1. Was sind die Aspekte objektorientierter Eigenschaften?
Antwort: Die Hauptaspekte von objektorientierten Merkmalen sind:
1) Abstract: Abstraktion ist der Prozess der Zusammenfassung der gemeinsamen Eigenschaften einer Objekttyp in eine Klasse von Objekten, einschließlich Datenabstraktion und Verhaltensabstraktion. Die Abstraktion konzentriert sich nur darauf, welche Attribute und Verhaltensweisen das Objekt hat, und achtet nicht darauf, was die Details dieser Verhaltensweisen sind.
2) Vererbung: Vererbung ist der Prozess der Erlangung von Vererbungsinformationen aus vorhandenen Klassen und Erstellen neuer Klassen. Die Klasse, die ererbte Informationen liefert, wird als übergeordnete Klasse (Superklasse, Basisklasse) bezeichnet. Die Klasse, die erbte Informationen erhält, wird als Unterklasse (abgeleitete Klasse) bezeichnet. Die Vererbung verleiht dem sich ändernden Softwaresystem ein gewisses Maß an Kontinuität, und die Vererbung ist auch ein wichtiges Mittel, um variable Faktoren im Programm zu verkörpern (wenn Sie es nicht verstehen können, lesen Sie bitte den Teil des Bridge -Modus in Dr. Yan Hongs "Java und Mustern" oder "Entwurfsmuster exquisites").
3) Kapselung: Es wird allgemein angenommen, dass die Kapselung Daten an die Methode der Betriebsdaten binden und der Zugriff auf Daten nur über die definierte Schnittstelle erreicht werden kann. Das Wesen von objektorientiertem Objekt ist es, die reale Welt als eine Reihe völlig autonomer und geschlossener Objekte darzustellen. Die Methode, die wir in einer Klasse schreiben, besteht darin, Implementierungsdetails zu verkapulieren. Wir schreiben eine Klasse sollen Daten- und Datenoperationen zusammenfassen. Es kann gesagt werden, dass Verpackungen alles verbergen sollen, was versteckt werden kann, und nur die einfachste Programmierschnittstelle in der Außenwelt bietet (Sie können über den Unterschied zwischen einer gewöhnlichen Waschmaschine und einer vollautomatischen Waschmaschine nachdenken. Es ist offensichtlich, dass die vollautomatische Waschmaschine besser verpackt ist und daher einfacher zu bedienen ist. Das Smartphone, das wir jetzt verwenden, ist auch gut genug verpackt, weil nur einige Knöpfe alles können.
4) Polymorphismus: Der Polymorphismus bezieht sich darauf, Objekte unterschiedlicher Subtypen unterschiedlich auf dieselbe Nachricht zu reagieren. Einfach ausgedrückt, es soll dieselbe Methode mit derselben Objektreferenz aufrufen, aber unterschiedliche Dinge tun. Polymorphismen werden in Kompilierungszeitpolymorphismen und Laufzeitpolymorphismen unterteilt. Wenn die Methode des Objekts als Dienst angesehen wird, das das Objekt für die Außenwelt erbracht hat, kann der Laufzeitpolymorphismus erklärt werden: Wenn System A. Zugriff auf die von System B bereitgestellten Dienste ist, hat System B mehrere Möglichkeiten zur Erbringung von Diensten, aber alles ist transparent zu System A (genau wie ein elektrischer Raver ist. Objekte, aber es weiß nicht, was die zugrunde liegende Implementierung des Netzteilsystems ist und wie es Strom erhält). Methodenüberladung implementiert das Kompilierungs-Time-Polymorphismus (auch als Vorbindung bezeichnet), während Methoden-Overrid-Polymorphismus (auch als Postbinding bekannt) implementiert. Laufzeit-Polymorphismus ist das Wesentliche an objektorientiertem. Um den Polymorphismus zu implementieren, müssen zwei Dinge durchgeführt werden: 1. Methode Umschreiben (die Unterklasse erbt die übergeordnete Klasse und schreibt vorhandene oder abstrakte Methoden in der übergeordneten Klasse um); 2. Objektmodellierung (in Bezug auf das Objekt des untergeordneten Typs mit der übergeordneten Referenz, so dass dieselbe Referenz dieselbe Methode aufnimmt, zeigt unterschiedliche Verhaltensweisen gemäß den verschiedenen Subklassenobjekten an).
2. Was ist der Unterschied zwischen dem Zugriff auf Modifikatoren öffentlich, privat, geschützt und nicht schriftlich (Standard)?
Antwort: Die Unterschiede sind wie folgt:
Umfang ist der gleiche wie die Bun -Unterklasse.
public √ √ √ √ √ √
geschützt √ √ √ ×
Standard √ √ × ×
privat √ × × ×
Die Standardeinstellung ist standardmäßig, wenn die Klassenmitglieder keine Änderung des Zugriffs schreiben. Standardmäßig entspricht es für andere Klassen im selben Paket der Öffentlichkeit und für andere Klassen, die sich nicht im selben Paket befinden. Geschützt entspricht der Öffentlichkeit zu Unterklassen und privat zu Klassen, die sich nicht in demselben Paket befinden und keine Eltern-Kind-Beziehung haben.
3. Ist String der grundlegendste Datentyp?
Antwort: Nein. Es gibt nur 8 grundlegende Datentypen in Java: Byte, Short, Int, Long, Float, Double, Char und Boolean; Mit Ausnahme des Basistyps (primitiver Typ) und des Aufzählungstyps (Aufzählungstyp) sind der Rest Referenztypen (Referenztyp).
4. Float F = 3,4; Ist es richtig?
Antwort: falsch. 3.4 ist eine doppelte Präzisionszahl. Das Zuweisen von Doppelblättern zu einem schwebenden Punkttyp (Float) verursacht Genauigkeitsverlust (Down-Casting, auch als Verengung bezeichnet). Sie müssen also Float F = (Float) 3.4 werfen; oder schreiben float f = 3.4f;.
5. Kurzes S1 = 1; S1 = S1 + 1; Stimmt etwas falsch? kurz S1 = 1; S1 += 1; Stimmt etwas nicht?
Antwort: Für kurze S1 = 1; S1 = S1 + 1; Da 1 ein Int -Typ ist, ist das Ergebnis des S1+1 -Betriebs ebenfalls ein Int -Typ, und ein Gusstyp ist erforderlich, um dem kurzen Typ einen Wert zuzuweisen. Und kurz S1 = 1; S1 += 1; kann korrekt kompiliert werden, weil S1+= 1; ist äquivalent zu S1 = (kurz) (S1 + 1); Es gibt implizite Abgüsse.
6. Gibt es ein Goto in Java?
Antwort: Goto ist ein reserviertes Wort in Java und wird in der aktuellen Version von Java nicht verwendet. (Eine Liste von Java -Schlüsselwörtern ist im Anhang des Buches "The Java Programming Language" angegeben, das von James Gosling (dem Vater von Java) geschrieben wurde, das Goto und Const enthält. Diese beiden sind jedoch Keywords, die derzeit unbrauchbar sind. Einige Orte nennen es reservierte Wörter. Reservierte Wörter)
7. Was ist der Unterschied zwischen INT und Ganzzahl?
Antwort: Java ist eine fast reine, objektorientierte Programmiersprache, aber für die Bequemlichkeit der Programmierung führt sie immer noch grundlegende Datentypen ein, die keine Objekte sind. Um diese grundlegenden Datentypen als Objekte zu betreiben, hat Java die entsprechende Wrapper -Klasse für jeden grundlegenden Datentyp eingeführt. Die Verpackungsklasse von INT ist ganzzahlig. Seit JDK 1.5 wurde ein automatischer Pack-/Unboxing -Mechanismus eingeführt, so dass die beiden zueinander umgewandelt werden können.
Java bietet Wrapper -Typen für jeden primitiven Typ:
Primitive Typen: Boolean, Char, Byte, Short, Int, Long, Float, Double
Verpackungstypen: Boolean, Charakter, Byte, kurz, ganzzahlig, lang, float, doppelt
Paket com.lovo; // Warum nach Hovertree.comPublic Class AutounBoxingTest fragen {public static void main (String [] args) {Integer a = new Integer (3); Ganzzahl B = 3; // Automatische Box 3 in Ganzzahltyp int c = 3; System.out.println (a == b); // FALSE Die beiden Referenzen verweisen nicht auf das gleiche Objektsystem.out.println (a == c); // true a automatisch unboxen in den type und vergleicht dann mit c}}Hinzugefügt: Ich habe kürzlich eine Interviewfrage gestoßen, die auch mit automatischen Packungen und Unboxing zusammenhängt. Der Code lautet wie folgt:
public class test03 {public static void main (String [] args) {Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System.out.println (f1 == f2); System.out.println (f3 == f4); }} // Hovertree.comWenn Sie es nicht verstehen, ist es leicht zu glauben, dass beide Ausgänge entweder wahr oder falsch sind. Zunächst ist es wichtig zu beachten, dass die vier Variablen F1, F2, F3 und F4 alle ganzzahligen Objekte sind, daher vergleicht der folgende == Operation nicht Werte, sondern Referenzen. Was ist die Essenz des Verpackens? Wenn wir einem Integer -Objekt einen Int -Wert zuweisen, werden wir den statischen Methodenwert der Ganzzahlklasse aufrufen. Wenn wir uns den Quell -Wertcode von ansehen, werden wir wissen, was los ist.
public static Integer valueOf (int i) {if (i> = integercache.low && i <= integercache.high) return IntegerCache.cache [i + (-integercache.low)]; Neue Ganzzahl zurückgeben (i); } // Hovertree.comIntegercache ist eine innere Ganzzahlklasse, und sein Code sieht so aus:
/** * Cache zur Unterstützung der Objektidentitätssemantik des Autoboxens für Werte zwischen * -128 und 127 (inklusive), wie von JLS gefordert. * * Der Cache wird bei der ersten Verwendung initialisiert. Die Größe des Cache * kann von {@code -xx: autoboxcachemax = <größe>} gesteuert werden. * Während der VM -Initialisierung kann Java.lang.Ineger.Inegercache.High Property * in den privaten Systemeigenschaften in der Klasse * sun.misc.vm gespeichert werden. * Hovertree.com */ private statische Klasse IntegerCache {static final int low = -128; statische endgültige int hoch; statischer endgültiger Ganzzahl -Cache []; static {// hoher Wert kann durch Eigenschaft int H = 127 konfiguriert werden; String IntegerCacheHighPropValue = sun.misc.vm.getSavedProperty ("java.lang.Ineger.Inegercache.high"); if (IntegerCacheHighPropValue! i = math.max (i, 127); // Maximale Arraygröße ist integer.max_value h = math.min (i, ginneger.max_value -(-low) -1); } catch (numberFormatexception nfe) {// Wenn die Eigenschaft nicht in ein int analysiert werden kann, ignorieren Sie sie. }} High = H; Cache = New Integer [(hoch - niedrig) + 1]; int j = niedrig; für (int k = 0; k <cache.length; k ++) cache [k] = new Integer (j ++); // Bereich [-128, 127] muss internalisiert werden (JLS7 5.1.7) Integercache durchsetzen.High> = 127; } private IntegerCache () {}}Einfach ausgedrückt, wenn der buchstäbliche Wert zwischen -128 und 127 liegt, ist das neue Integer -Objekt nicht neu, aber das Ganzzahlobjekt im konstanten Pool wird direkt verwiesen. Daher ist das Ergebnis von F1 == F2 in der obigen Interviewfrage wahr, und das Ergebnis von F3 == F4 ist falsch. Je einfacher die Interviewfragen, desto mehr Rätsel gibt es, und der Interviewer muss über erhebliche Fähigkeiten verfügen.
8. Was ist der Unterschied zwischen & und &&?
Antwort: Es gibt zwei Verwendungen des & Operators: (1) bitweise und (2) logisch und. Der && Operator ist ein Kurzschluss und ein Vorgang. Der Unterschied zwischen Logik und Kurzschaltungen ist sehr groß, obwohl beide erfordern, dass die booleschen Werte am linken und rechten Ende des Bedieners dem Wert des gesamten Ausdrucks treu sind. && wird als Kurzschlussoperation bezeichnet, da der Ausdruck auf der rechten Seite, wenn der Wert des Ausdrucks links von && falsch ist, der Ausdruck auf der rechten Seite direkt abgeschlossen wird und die Operation nicht durchgeführt wird. Oft müssen wir && anstelle von && verwenden. Wenn Sie beispielsweise überprüfen, ob der Benutzername nicht null ist und keine leere Zeichenfolge ist, sollte er als: Benutzername geschrieben werden! Die Reihenfolge der beiden kann nicht ausgetauscht werden und der & Bediener kann nicht verwendet werden, da wenn die erste Bedingung nicht zutrifft, kann der Equals -Vergleich der Zeichenfolge überhaupt nicht durchgeführt werden, sonst wird eine Nullpointerexception generiert. Hinweis: Gleiches gilt für den Unterschied zwischen logisch oder operator (|) und kurzer Kreislauf oder Operator (||).
Hinzugefügt: Wenn Sie mit JavaScript vertraut sind, können Sie möglicherweise die Leistung von Kurzschlusscomputer mehr spüren. Wenn Sie ein Meister von JavaScript werden möchten, spielen Sie zunächst ein Short-Circuit-Computing.
9. Erläutern Sie die Verwendung von Stapel-, Haufen- und statischen Speicherbereichen im Speicher.
ANTWORT: Normalerweise definieren wir eine Variable des Basistyps, eine Objektreferenz und die Speicher von Funktionsaufrufen vor Ort, die alle den Stapelraum im Speicher verwenden. und die über das neuen Schlüsselwort und den Konstruktor erstellten Objekte werden im Haufenraum platziert. Die Literale im Programm, wie 100, "Hallo" und konstante, die direkt geschrieben wurden, werden im statischen Speicherbereich platziert. Der Stack Space funktioniert am schnellsten, ist aber auch sehr klein. Normalerweise wird eine große Anzahl von Objekten im Haufen Speicherplatz platziert, und der gesamte Speicher, einschließlich des virtuellen Speichers auf der Festplatte, kann als Haufenraum verwendet werden.
String str = new String ("Hallo");
In der obigen Anweisung wird STR auf den Stapel platziert, das mit Neue erstellte String -Objekt wird auf dem Haufen platziert und das wörtliche "Hallo" auf dem statischen Speicherbereich platziert.
Ergänzung: Eine neuere Version von Java verwendet eine Technologie namens "Escape Analysis", mit der einige lokale Objekte auf den Stapel platzieren können, um die Betriebsleistung von Objekten zu verbessern.
10. Was ist Mathematik (11,5) gleich? Was ist math.round (-11.5) gleich?
Antwort: Der Rückgabewert der Mathematik (11,5) beträgt 12 und der Rückgabewert von Math. Das Prinzip der Rundung besteht darin, den Parameter 0,5 hinzuzufügen und dann nach unten zu runden.
11. Kann swtich auf Byte handeln, lange auf String?
Antwort: In der frühen JDK, in Switch (EXPR), kann EXPR Byte, Short, Char und Int sein. Ab Version 1.5 hat Java Enumstypen (Enum) eingeführt, und EXPR kann auch Auslauf sein, ab Version 1.7 von JDK und auch einer String (String). Langer Typ ist nicht erlaubt.
12. Verwenden Sie die effizienteste Methode, um 2 -mal 8 zu berechnen?
Antwort: 2 << 3 (3 -Bit auf der linken Seite entspricht dem Multiplizieren mit 2 mit 3 und das Bewegen von 3 Bits rechts entspricht der Division durch 2 auf die Leistung von 3).
Ergänzung: Wenn wir die HashCode -Methode für die von uns geschriebene Klasse neu schreiben, sehen wir möglicherweise den unten angegebenen Code. Tatsächlich verstehen wir nicht ganz, warum wir eine solche Multiplikation verwenden, um einen Hash -Code (Hash -Code) zu generieren, und warum ist diese Nummer eine Primzahl und warum wird die Nummer 31 normalerweise ausgewählt? Sie können die Antworten auf die ersten beiden Fragen baidu machen. Wählen Sie 31, da Schicht- und Subtraktionsvorgänge anstelle von Multiplikation verwendet werden können, wodurch eine bessere Leistung erzielt wird. Wenn Sie davon sprechen, haben Sie vielleicht gedacht: 31 * num <==> (num << 5) - Num, das Verlagerung der linken 5 -Bit entspricht dem Multiplizieren mit 2 mit der 5. Leistung (32) und das Subtrahieren selbst entspricht dem Multiplizieren mit 31. Alle VMs können diese Optimierung automatisch vervollständigen.
Paket com.loonstudio; öffentliche Klasse PhoneNumber {private int AreaCode; privates Zeichenfolgenpräfix; private String -Leinenzahl; @Override public int HashCode () {final int prime = 31; int result = 1; Ergebnis = Prime * Ergebnis + AreaCode; result = prime * result + ((linenumber == null)? 0: linenumber.hashCode ()); result = prime * result + ((Präfix == null)? 0: Präfix.hashCode ()); Rückgabeergebnis; } @Override public boolean Equals (Objekt obj) {if (this == obj) return true; if (obj == null) return false; if (getClass ()! = obj.getClass ()) return false; PhoneNumber Andere = (PhoneNumber) obj; if (AreaCode! = other.areacode) return false; if (linenumber == null) {if (other.linenumber! = null) return false; } else if (! linenumber.equals (other.linEnumber)) return false; if (Präfix == null) {if (other.prefix! = null) return false; } else if (! prefix.equals (other.prefix)) return false; zurückkehren; }} // Warum nach Hovertree.com fragen13. Gibt es eine Länge () -Methode für Arrays? Gibt es eine Länge () -Methode für String?
Antwort: Das Array hat keine Länge () -Methode, sondern ein Längenattribut. String hat eine Länge () -Methode. In JavaScript wird das Erhalten der Länge der Zeichenfolge durch das Längenattribut erhalten, das leicht mit Java verwechselt wird.
14. Wie kann man in Java aus den aktuellen mehrfachen verschachtelten Loops ausbrechen?
Antwort: Fügen Sie eine Marke wie eine vor der äußersten Schleife hinzu und verwenden Sie dann Break A; Mehrere Schleifen können gebrochen werden. (Java unterstützt markierte Break- und Fortsetzung von Aussagen, und ihre Funktionen sind ein bisschen ähnlich wie bei GOTO -Aussagen in C und C ++, aber genau wie die Vermeidung von GOTO sollten Sie markiertes Break vermeiden und weitermachen, da es Ihr Programm nicht eleganter macht und oft sogar den gegenteiligen Effekt hat, sodass diese Syntax tatsächlich besser ist.))
15. Kann der Konstruktor außer Kraft gesetzt werden?
Antwort: Der Konstruktor kann nicht vererbt werden, daher kann er nicht umgeschrieben werden, aber er kann überladen werden.
16. Zwei Objekte haben den gleichen Wert (x.equals (y) == true), aber sie können unterschiedliche Hash -Codes haben. Ist das richtig?
Antwort: Nein, wenn die beiden Objekte x und y X.Equals (y) == wahr erfüllen, sollte ihr Hash -Code der gleiche sein. Java sieht die EQAULS -Methode und die HashCode -Methode wie folgt vor: (1) Wenn zwei Objekte gleich sind (Equals -Methode gibt true), müssen ihre Hashcode -Werte gleich sein. (2) Wenn die Hashcodes der beiden Objekte gleich sind, sind sie nicht unbedingt gleich. Natürlich müssen Sie nicht wie erforderlich tun, aber wenn Sie gegen die oben genannten Prinzipien verstoßen, werden Sie feststellen, dass bei der Verwendung von Containern dasselbe Objekt in der SET -Sammlung angezeigt werden kann und die Effizienz des Hinzufügens neuer Elemente stark reduziert wird (für Systeme mit Hash -Speicher, häufige Konflikte in Hash -Codes verursachen einen starken Rückgang der Zugangsleistung).
Ergänzung: Viele Java -Programme wissen über Gleich- und Hashcode -Methoden, aber viele Menschen wissen es einfach. In Joshua Blochs Meisterwerk "Effektives Java" (viele Softwareunternehmen, "effektive Java", "Java-Programmiergedanken" und "Refactoring: Verbesserung der Qualität des vorhandenen Code" sind Must-Read-Bücher von Java-Programmen. Wenn Sie es nicht gelesen haben, beeilen Sie sich. Richtig) und Symmetrie (X.Equals (y) zurückgegeben, y.equals (x) muss auch sein, dass es true zurückgeben muss), Transitivität (X.Equals (y) und y.equals (z) müssen ebenfalls wahr zurückgeben) und Konsistenz (wenn die Objektinformationen, die von x und y verwiesen werden, werden nicht geändert. Zu den Tricks zur Implementierung hochwertiger Equal-Methoden gehören: 1.. Verwenden Sie den Operator ==, um zu überprüfen, ob der Parameter ein Verweis auf dieses Objekt ist "; 2. Überprüfen Sie den Instanzoperator, um "ob der Parameter der richtige Typ ist". 3. Überprüfen Sie für wichtige Attribute in der Klasse, ob die an das Objekt übergebenen Attributen mit ihm übergeben wurden. 4. Nachdem Sie die Equals -Methode geschrieben haben, fragen Sie sich, ob sie Symmetrie, Transitivität und Konsistenz erfüllt. 5. Schreiben Sie immer Hashcode neu, wenn Sie das gleiche Schreiben entsprechen; 6. Ersetzen Sie das Objektobjekt nicht in den Equals -Methodenparametern durch andere Typen und vergessen Sie die @Override -Annotation beim Umschreiben nicht.
17. Kann die String -Klasse vererbt werden?
Antwort: Die String -Klasse ist eine endgültige Klasse und kann nicht vererbt werden.
Ergänzung: Die Erbe -String ist ein falsches Verhalten an sich. Der beste Weg, String-Typen wiederzuverwenden, ist Association (HAS-A) eher als Vererbung (IS-A).
18. Wenn ein Objekt als Parameter an eine Methode übergeben wird, kann diese Methode die Eigenschaften des Objekts ändern und das geänderte Ergebnis zurückgeben. Ist es also ein Wertpass oder ein Referenzpass hier?
Antwort: Es ist Wertübertragung. Die Java -Programmiersprache übergibt nur Parameter mit Werten. Wenn eine Objektinstanz als Parameter in eine Methode übergeben wird, ist der Wert des Parameters eine Referenz auf das Objekt. Die Eigenschaften eines Objekts können während des Anrufvorgangs geändert werden, aber der Verweis auf das Objekt wird sich niemals ändern. In C ++ und C#kann der Wert der bestandenen Parameter durch Übergabe von Referenzen oder Übertragung von Parametern geändert werden.
Ergänzung: Es ist wirklich unpraktisch, in Java keine Referenzen zu übergeben, die in Java 8 nicht verbessert wurden. Genau auf diese Weise erscheinen eine große Anzahl von Wrapper -Klassen in dem in Java geschriebenen Code (die Referenzen, die durch Methodenaufrufe in einen Wrapper -Klassen geändert werden müssen, und dann das Wrapper -Objekt in eine Methode zu übergeben). Dieser Ansatz macht den Code nur aufgebläht, insbesondere für Entwickler, die von C und C ++ zu Java -Programmierern zu unerträglichen Umständen umwandeln.
19. Was ist der Unterschied zwischen String und StringBuilder und StringBuffer?
Antwort: Die Java -Plattform bietet zwei Arten von Zeichenfolgen: String- und StringBuffer/StringBuilder, die Saiten speichern und manipulieren können. Wobei String eine schreibgeschützte Zeichenfolge ist, was bedeutet, dass der Inhalt der von der Zeichenfolge verwiesenen Zeichenfolge nicht geändert werden kann. Die String -Objekte, die von den Klassen StringBuffer und StringBuilder -Klassen dargestellt werden, können direkt geändert werden. StringBuilder wurde in JDK 1.5 vorgestellt. Es ist genau das gleiche wie die Stringbuffer -Methode. Der Unterschied besteht darin, dass es in einer einzelnen Thread -Umgebung verwendet wird, da alle Aspekte nicht durch synchronisiert werden, sodass es etwas effizienter ist als StringBuffer.
Ergänzung 1: Es gibt eine Interviewfrage: Gibt es eine Situation, in der die Verwendung von + zur String -Verkettung besser ist, als die Anhangsmethode des StringBuffer/StringBuilder -Objekts aufzurufen? Wenn die nach der Verbindung bereits im statischen Speicherbereich vorhandene Zeichenfolge erhalten wird, ist die Verwendung von + für die String -Verkettung besser als die Anhangsmethode von StringBuffer/StringBuilder.
Ergänzung 2: Das Folgende ist auch eine Interviewfrage, in der die Ausgabe des Programms gestellt wird, um festzustellen, ob Sie die richtige Antwort geben können.
Paket com.lovo; // Warum nach Hovertree.comPublic Class StringEqualtest fragen {public static void main (String [] args) {String a = "Programmierung"; Zeichenfolge b = neuer String ("Programmierung"); String C = "Programm" + "Ming"; System.out.println (a == b); System.out.println (a == c); System.out.println (A.Equals (b)); System.out.println (A.Equals (c)); System.out.println (A.intern () == b.intern ()); }}20. Der Unterschied zwischen Überlast und Überschrift. Können überlastete Methoden anhand des Rückgabetyps unterschieden werden?
Antwort: Sowohl Methodenüberladung als auch Umschreiben sind Möglichkeiten zur Implementierung von Polymorphismus. Der Unterschied besteht darin, dass die ersteren Implementierung des Kompilierzeitpolymorphismus, während die letzteren Run-Time-Polymorphismus implementiert. Überlastung tritt in einer Klasse auf. Wenn eine Methode mit demselben Namen eine andere Parameterliste aufweist (verschiedene Parametertypen, unterschiedliche Anzahl von Parametern oder beides), wird sie als Überladung angesehen. Die Umschreibung erfolgt zwischen der Unterklasse und der übergeordneten Klasse. Umschreibe erfordert, dass die umgeschriebene Methode der Subklasse und die übergeordnete Klasse den gleichen Rückgabetyp wie die umgeschriebene Methode der übergeordneten Klasse haben, die einen besseren Zugriff ist als die umgeschriebene Methode der übergeordneten Klasse und kann nicht mehr Ausnahmen deklarieren als die umgeschriebene Methode der Elternklasse (Risches Substitutionsprinzip). Überladung hat keine besonderen Anforderungen für Rückgabetypen.
Ergänzung: Huawei stellte einmal eine Frage in der Interviewfrage: Warum können Sie Überladen nicht basierend auf dem Rückgabetyp unterscheiden und Ihre Antwort mitteilen?
21. Beschreiben Sie das Prinzip und den Mechanismus von JVM -Ladeklassendateien?
Antwort: Das Laden von Klassen in der JVM wird von einem Klassenlader (Classloader) und seinen Unterklassen implementiert. Der Klassenlader in Java ist eine wichtige Java -Laufzeit -Systemkomponente, die für das Auffinden und Laden von Klassen in Klassendateien zur Laufzeit verantwortlich ist.
Wieder auffüllen:
1. Aufgrund der plattformübergreifenden Natur von Java ist das kompilierte Java-Quellprogramm kein ausführbares Programm, sondern eine oder mehrere Klassendateien. Wenn ein Java -Programm eine Klasse verwenden muss, stellt die JVM sicher, dass die Klasse geladen, verbunden (verifiziert, vorbereitet und analysiert) und initialisiert wurde. Das Laden der Klasse bezieht sich auf das Lesen von Daten aus der Klasse -Klassendatei in den Speicher. Normalerweise erstellen Sie ein Byte -Array, um es in die .Class -Datei zu lesen und dann ein Klassenobjekt zu generieren, das der geladenen Klasse entspricht. Nach Abschluss des Ladens ist das Klassenobjekt noch unvollständig, sodass die Klasse zu diesem Zeitpunkt nicht verfügbar ist. Wenn die Klasse geladen ist, tritt sie in die Verbindungsstufe ein. Diese Stufe umfasst drei Schritte: Überprüfung, Vorbereitung (Zuweisung von Speicher für statische Variablen und Festlegen des Standardwerfwerts) und Parsen (Ersetzen Sie Symbolreferenzen durch direkte Referenzen). Schließlich initialisiert der JVM die Klasse, einschließlich: 1. Wenn die Klasse eine direkte übergeordnete Klasse hat und die Klasse nicht initialisiert wurde, wird die übergeordnete Klasse zuerst initialisiert. 2. Wenn in der Klasse Initialisierungsanweisungen vorhanden sind, werden diese Initialisierungsanweisungen wiederum ausgeführt.
2. Die Klassenbelastung erfolgt durch Klassenloader, einschließlich: Root Loader (Bootstrap), Erweiterungslader (Erweiterung), Systemlader (System) und benutzerdefinierter Klassenlader (Unterklasse von Java.lang.Classloader). Ausgehend von JDK 1.2 übernimmt der Klassenbeladungsprozess den Vater -Delegationsmechanismus (PDM). PDM sorgt besser für die Sicherheit der Java -Plattform. In diesem Mechanismus ist der Startstrap des JVM der Stammlader, und andere Lader haben nur einen übergeordneten Klassenlader. Das Laden der Klasse fordert zuerst den übergeordneten Klassenloader zum Laden an, und der Lader der übergeordneten Klassen wird nur durch den Unterklassen -Lader geladen, wenn er machtlos ist. Die JVM liefert keine Hinweise auf Bootstrap auf Java -Programme. Hier sind einige Anweisungen für mehrere Klassenlader:
a) Bootstrap: Es wird im Allgemeinen mit lokalem Code implementiert und ist für das Laden der grundlegenden Kernklassenbibliothek von JVM (RT.Jar) verantwortlich.
b) Erweiterung: Laden Sie die Klassenbibliothek aus dem von der Eigenschaft java.ext.dirs festgelegten Verzeichnis, und der übergeordnete Lader ist Bootstrap;
C) System: Auch als Anwendungsklassenlader bezeichnet, ist seine übergeordnete Klasse Erweiterung. Es ist der am häufigsten verwendete Klassenlader. Es zeichnet Klassen aus dem Verzeichnis auf, das in der Umgebungsvariablenklasse oder Systemattribut Java.class.Path angegeben wurde, und ist der Standard-Elternlader des benutzerdefinierten Loaders.
22. Kann ein chinesischer Charakter in einer Char -Typ -Variablen gespeichert werden? Warum?
Antwort: Der Zeichen -Typ kann ein chinesisches Zeichen speichern, da die in Java verwendete Codierung unicode ist (es wird keine spezifische Codierung ausgewählt, und Zeichen werden direkt in der Zeichensatznummer verwendet, was die einzige einheitliche Methode ist). Ein Zeichenentyp nimmt 2 Bytes (16bit) auf, daher ist es kein Problem, ein Chinesisch zu setzen.
Ergänzung: Die Verwendung von Unicode bedeutet, dass Zeichen unterschiedliche Manifestationen innerhalb und außerhalb des JVM haben und beide Unicode innerhalb des JVM sind. Wenn dieses Zeichen von der JVM nach außen übertragen wird (z. B. im Dateisystem gespeichert), ist eine Codierungskonvertierung erforderlich. Daher hat Java Byte -Streams und Zeichenströme sowie Konvertierungsströme, die zwischen Zeichenströmen und Byte -Streams wie InputStreamReader und OutputStreamReader konvertieren. Diese beiden Klassen sind Adapterklassen zwischen Byte -Streams und Zeichenströmen und übernehmen die Aufgabe der Codierung der Konvertierung. Für C -Programmierer, um eine solche Codierungsumwandlung abzuschließen, verlassen sie sich wahrscheinlich auf die Merkmale der gemeinsamen Gewerkschaft (Union/Community), um zu erreichen.
23. Was sind die Ähnlichkeiten und Unterschiede zwischen abstrakter Klasse und Schnittstelle?
Antwort: Sowohl abstrakte Klassen als auch Schnittstellen können nicht instanziiert werden, aber Verweise auf abstrakte Klassen und Schnittstellentypen können definiert werden. Wenn eine Klasse eine abstrakte Klasse erbt oder eine Schnittstelle implementiert, muss sie alle darin enthaltenen abstrakten Methoden implementieren, ansonsten muss die Klasse noch als abstrakte Klasse deklariert werden. Schnittstellen sind abstrakter als abstrakte Klassen, da Konstruktoren in abstrakten Klassen definiert werden können und es abstrakte Methoden und konkrete Methoden geben können, während Konstruktoren nicht in Schnittstellen definiert werden können und alle Methoden in ihnen abstrakte Methoden sind. Mitglieder in abstrakten Klassen können privat, standardmäßig, geschützt und öffentlich sein, während Mitglieder in Schnittstellen alle öffentlich sind. Mitgliedervariablen können in abstrakten Klassen definiert werden, während die in Schnittstellen definierten Elementvariablen tatsächlich Konstanten sind. Klassen mit abstrakten Methoden müssen als abstrakte Klassen deklariert werden, und abstrakte Klassen haben nicht unbedingt abstrakte Methoden.
24. Was ist der Unterschied zwischen statischen verschachtelten Klassen und inneren Klassen (innere Klasse)?
Antwort: Die statische verschachtelte Klasse ist eine innere Klasse, die als statisch deklariert ist und so instanziiert werden kann, dass sie sich auf externe Klasseninstanzen verlassen. Die üblichen inneren Klassen müssen nach dem Instanziieren der externen Klasse instanziiert werden, und die Syntax sieht, wie unten gezeigt, ziemlich seltsam aus.
Paket com.lovo; / ** * Pokerklasse (ein Deck von Poker) Warum nach Hovertree.com * * */ public class Poker {private statische String [] Suites = {"Spade", "Rose", "Grass Flower", "Cube"} fragen; private static int [] Faces = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; private Karte [] Karten; / *** Konstruktor**/ public poker () {cards = new Card [52]; für (int i = 0; i <Suites.length; i ++) {für (int j = 0; j <faces.length; j ++) {karten [i * 13+j] = new Card (Suites [i], Gesichtsfaktoren [j]); }}} / ** * shuffle (zufällig außerhalb der Reihenfolge) * * / public void shuffle () {for (int i = 0, len = cards.length; i <len; i ++) {int index = (int) (math.random () * len); Kartentemp = Karten [Index]; Karten [Index] = Karten [i]; Karten [i] = temp; }} / *** Kartengeschäft* @param Index Die Position des Deals** / public Card Deal (int Index) {return Cards [index]; } / ** * Kartenklasse (ein Stück Poker) * [interne Klasse] * @author luo hao * * / public class Card {private String Suite; // Anzug privat int face; // punkte public card (String Suite, int face) {this.suite = Suite; this.face = face; } @Override public String toString () {String facestr = ""; Switch (Gesicht) {Fall 1: fquestr = "a"; brechen; Fall 11: fquestr = "j"; brechen; Fall 12: fquestr = "q"; brechen; Fall 13: fquestr = "k"; brechen; Standard: facestr = string.Valueof (Gesicht); } return Suite + facestry; }}} Testklasse:
Paket com.lovo; Klasse pokertest {public static void main (String [] args) {Poker poker = new Poker (); poker.shuffle (); // shuffle poker.card c1 = poker.deal (0); // dient der ersten Karte // für nicht statische interne Klassenkarten // kann nur über das Pokerobjekt Poker für externe Klasse erstellt werden. // Erstellen Sie eine Karte selbst system.out.println (c1); // das erste System.out.println (C2); // Druck: Rotes Herz A}} // Warum nach Hovertree.com fragen25. Wird es in Java ein Speicherleck geben? Bitte beschreiben Sie es kurz.
Antwort: Theoretisch wird Java keine Speicherlecks haben, da es einen Müllsammler (GC) hat (dies ist auch ein wichtiger Grund, warum Java in der serverseitigen Programmierung häufig verwendet wird). In der tatsächlichen Entwicklung kann es jedoch nutzlos, aber zugängliche Objekte geben, und diese Objekte können nicht durch GC recycelt werden und Speicherlecks treten auf. Ein Beispiel ist, dass die Objekte in der Sitzung von Hibernate (Stufe 1 -Cache) anhaltend sind und der Müllsammler diese Objekte nicht recyceln, aber in diesen Objekten können nutzlose Müllobjekte vorhanden sein. Das folgende Beispiel zeigt auch das Speicherleck in Java:
Paket com.lovo; // Warum nach Hovertree.comimport Java.util.Arrays fragen; Import Java.util.EmptyStackexception; öffentliche Klasse Mystack <t> {private t [] Elemente; private int size = 0; private statische endgültige init init_capacity = 16; public mystack () {Elements = (t []) neues Objekt [init_capacity]; } public void push (t elem) {sealEcapacity (); Elemente [Größe ++] = Elem; } public t pop () {if (size == 0) werfen neue leerStackexception (); Rückgabeelemente [-Größe]; } private void ensureCapacity() { if(elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); }}}上面的代码实现了一个栈(先进后出(FILO))结构,乍看之下似乎没有什么明显的问题,它甚至可以通过你编写的各种单元测试。然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用(obsolete reference)。在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。如果一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即使这样的对象只有少数几个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端情况下会引发Disk Paging(物理内存与硬盘的虚拟内存交换数据),甚至造成OutOfMemoryError。
26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
27、静态变量和实例变量的区别?
答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。在Java开发中,上下文类和工具类中通常会有大量的静态成员。
28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象并没有被初始化。
29、如何实现对象克隆?
答:有两种方式:
1.实现Cloneable接口并重写Object类中的clone()方法;
2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。
package com.lovo; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class MyUtil { private MyUtil() { throw new AssertionError(); } public static <T> T clone(T obj) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bout); oos.writeObject(obj); ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bin); return (T) ois.readObject(); // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源} } //何问起hovertree.com下面是测试代码:
package com.lovo; import java.io.Serializable; /** * Human* @author Luo Hao* */ class Person implements Serializable { private static final long serialVersionUID = -9102017020286042305L; private String name; // Name private int age; // Age private Car car; // Car public Person(String name, int age, Car car) { this.name = name; this.age = Alter; this.car = car; } public String getName () {return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", car=" + car + "]"; } } /** * Car class* @author Luo Hao* */ class Car implements Serializable { private static final long serialVersionUID = -5713945027627603702L; private String brand; // Brand private int maxSpeed; // Top speed public Car(String brand, int maxSpeed) { this.brand = brand; this.maxSpeed = maxSpeed; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } @Override public String toString() { return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]"; } } //Why ask about hovertree.comclass CloneTest { public static void main(String[] args) { try { Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300)); Person p2 = MyUtil.clone(p1); // Deep cloning p2.getCar().setBrand("BYD"); // Modify the brand attributes of the cloned Person object p2-associated car object// The original Person object p1-associated car will not be affected in any way// Because when cloning Person object, the car object associated with it is also cloned System.out.println(p1); } catch (Exception e) { e.printStackTrace(); }}}注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。
30、GC 是什么?为什么要有GC?
答: GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
与垃圾回收相关的JVM参数:
-Xms / -Xmx --- 堆的初始大小/ 堆的最大大小
-Xmn --- 堆中年轻代的大小
-XX:-DisableExplicitGC --- 让System.gc()不产生任何作用
-XX:+PrintGCDetail --- 打印GC的细节
-XX:+PrintGCDateStamps --- 打印GC操作的时间戳
31、String s=new String(“xyz”);创建了几个字符串对象?
答:两个对象,一个是静态存储区的"xyz",一个是用new创建在堆上的对象。
32、接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)?
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承具体类,但前提是具体类必须有明确的构造函数。
33、一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。
34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?
答:可以继承其他类或实现其他接口,在Swing编程中常用此方式来实现事件监听和回调。
35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
36、Java 中的final关键字有哪些用法?
答: (1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
37、指出下面程序的运行结果:
class A{ static{ System.out.print("1"); } public A(){ System.out.print("2"); } } class B extends A{ static{ System.out.print("a"); } public B(){ System.out.print("b"); } } //Why ask about hovertree.compublic class Hello{ public static void main(String[] args){ A ab = new B(); ab = new B(); }}答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
38、数据类型之间的转换:
1)如何将字符串转换为基本数据类型?
2)如何将基本数据类型转换为字符串?
Antwort:
1)调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;
2)一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf(…)方法返回相应字符串
39、如何实现字符串的反转及替换?
答:方法很多,可以自己写实现也可以使用String或StringBuffer / StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:
public static String reverse(String originStr) { if(originStr == null || originStr.length() <= 1) return originStr; return reverse(originStr.substring(1)) + originStr.charAt(0); } //何问起hovertree.com40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?
答:代码如下所示:
String s1 = "你好";String s2 = newString(s1.getBytes("GB2312"), "ISO-8859-1");41、日期和时间:
1)如何取得年月日、小时分钟秒?
2)如何取得从1970年1月1日0时0分0秒到现在的毫秒数?
3)如何取得某月的最后一天?
4)如何格式化日期?
答:操作方法如下所示:
1)创建java.util.Calendar 实例,调用其get()方法传入不同的参数即可获得参数所对应的值
2)以下方法均可获得该毫秒数:
Calendar.getInstance().getTimeInMillis(); System.currentTimeMillis(); //何问起hovertree.com
3)示例代码如下:
Calendar time = Calendar.getInstance(); time.getActualMaximum(Calendar.DAY_OF_MONTH); //何问起hovertree.com
4)利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。
42、打印昨天的当前时刻。
Antwort:
public class YesterdayCurrent { public static void main(String[] args){ Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); System.out.println(cal.getTime()); } } //何问起hovertree.com43、比较一下Java 和JavaSciprt。
答: JavaScript 与Java是两个公司开发的不同的两个产品。Java 是原Sun 公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言,它的前身是LiveScript;而Java 的前身是Oak语言。
下面对两种语言间的异同作如下比较:
1)基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;
2)解释和编译:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;
3)强类型变量和类型弱变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量声明,采用其弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;
4)代码格式不一样。
补充:上面列出的四点是原来所谓的标准答案中给出的。其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。目前的编程语言的发展趋势是函数式语言和动态语言。在Java中类(class)是一等公民,而JavaScript中函数(function)是一等公民。对于这种问题,在面试时还是用自己的语言回答会更加靠谱。
44、什么时候用assert?
答: assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后, assertion检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式计算为false,那么系统会报告一个AssertionError。
断言用于调试目的:
assert(a > 0); // throws an AssertionError if a <= 0
断言可以有两种形式:
assert Expression1;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。
断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用-enableassertions 或者-ea 标记。
要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。
要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。
45、Error 和Exception 有什么区别?
答: Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
Supplement: During the interview with Motorola in 2005, I asked a question like "If a process reports a stack overflow run-time error, what's the most possible cause?", giving four options a. lack of memory; B. write on an invalid memory space; C. recursive function calling; D. array index out of boundary. Java programs may also encounter StackOverflowError when running. This is an error that cannot be recovered, so I can only re-modify the code. The answer to this interview question is c. If you write recursion that cannot converge quickly, it is very likely to cause a stack overflow error, as shown below:
package com.lovo; public class StackOverflowErrorTest { public static void main(String[] args) { main(null); } } //何问起hovertree.com因此,用递归编写程序时一定要牢记两点:1. 递归公式;2. 收敛条件(什么时候就不再递归而是回溯了)。
46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。
47、Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?
答: Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw 语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的try 语句。
48、运行时异常与受检异常有何异同?
答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《Effective Java》中对异常的使用给出了以下指导原则:
不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)
对可以恢复的情况使用受检异常,对编程错误使用运行时异常避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)
优先使用标准的异常每个方法抛出的异常都要有文档保持异常的原子性不要在catch中忽略掉捕获到的异常
49、列出一些你常见的运行时异常?
Antwort:
ArithmeticException(算术异常)
ClassCastException (类转换异常)
IllegalArgumentException (非法参数异常)
IndexOutOfBoundsException (下表越界异常)
NullPointerException (空指针异常)
SecurityException (安全异常)
50、final, finally, finalize 的区别?
答: final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final 的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final 的方法也同样只能使用,不能在子类中被重写。finally:通常放在try…catch的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。finalize:Object类中定义的方法,Java中允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize() 方法可以整理系统资源或者执行其他清理工作。
Das obige ist der gesamte Inhalt dieses Artikels. I hope it will be helpful to everyone in the Java interview, and I hope everyone will support Wulin.com more.