Heim >Java >javaLernprogramm >Die 10 beliebtesten Java-Fragen zum Stackoverflow
1. Warum erhält man ein seltsames Ergebnis, wenn man zwei (1927) Mal subtrahiert?
(3623 Likes)
Wenn Sie das folgende Programm ausführen, analysiert das Programm zwei um 1 Sekunde getrennte Datumszeichenfolgen und vergleicht sie:
public static void main(String[] args) throws ParseException { SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String str3 = "1927-12-31 23:54:07"; String str4 = "1927-12-31 23:54:08"; Date sDt3 = sf.parse(str3); Date sDt4 = sf.parse(str4); long ld3 = sDt3.getTime() /1000; long ld4 = sDt4.getTime() /1000; System.out.println(ld4-ld3); }
Die Ausgabe ist:
353
Warum ist ld4-ld3 nicht 1 (weil ich möchte, dass der Unterschied zwischen den beiden Zeiten eine Sekunde beträgt), sondern 353?
Wenn Sie zu jeder Datumszeichenfolge eine Sekunde hinzufügen:
String str3 = "1927-12-31 23:54:08"; String str4 = "1927-12-31 23:54:09";
Das Ergebnis von ld4-ld3 ist 1.
sun.util.calendar.ZoneInfo[id="Asia/Shanghai", offset=28800000,dstSavings=0, useDaylight=false, transitions=19, lastRule=null] Locale(Locale.getDefault()): zh_CN
Lösung
Dies ist die Zeitzone von Shanghai und am 31. Dezember gibt es eine Änderung.
Auf dieser Website erfahren Sie Einzelheiten zu den Zeitzonenänderungen Shanghais im Jahr 1927. Im Grunde wird es um Mitternacht Ende 1927 immer um 5 Minuten und 52 Sekunden zurückgesetzt. „1927-12-31 23:54:08“ kommt also tatsächlich zweimal vor, und es sieht so aus, als hätte Java das letzte Mal als lokales Datum und Uhrzeit geparst, was den Unterschied verursacht.
2. Ist Java „Übergabe per Referenz“ oder „Übergabe per Wert“?
(2480 „Gefällt mir“-Angaben)
Ich habe immer gedacht, dass Java nur eine Referenz ist, aber ich habe eine Reihe von Blogs (wie diesen) gelesen, die etwas anderes behaupteten. Ich glaube nicht, dass ich den Unterschied zwischen ihnen verstehe.
Gib mir eine Erklärung?
Lösung
Java war schon immer eine Wertübergabe. Leider haben sie sich entschieden, Zeiger als Referenzen zu bezeichnen, sodass Neulinge immer verwirrt sind. Weil diese Referenzen auch als Wert übergeben werden.
3. Eine Frage zum Java-Operator +=
(2223 Likes)
Bis heute denke ich an dieses Beispiel:
i += j;
Just A Abkürzung:
i = i + j;
Aber wenn Sie dies tun:
int i = 5; long j = 8;
Allerdings kann i = i + j;
Das bedeutet i += j; ist es tatsächlich die Abkürzung von i = (Typ von i) (i + j)?
Lösungen
Es gibt immer Leute, die solche Fragen stellen, und JLS hat die Antworten. Siehe §15.26.2 Zusammengesetzte Zuweisungsoperatoren. Auszug:
E1 op= Der zusammengesetzte Zuweisungsausdruck vom Typ E2 entspricht E1 = (T)((E1) op (E2)), wobei T der Typ von E1 ist, der Unterschied besteht darin, dass E1 der Typ ist nur einmal berechnet.
Ein Beispiel, zitiert aus §15.26.2
[...] Der folgende Code ist korrekt:
short x = 3; x += 4.6;
Das Ergebnis von x ist gleich 7, weil it Entspricht:
short x = 3; x = (short)(x + 4.6);
Mit anderen Worten, Ihre Annahme ist richtig.
4. Was ist der Unterschied zwischen HashMap und Hashtable
(1769 Likes)
Was ist der Unterschied zwischen HashMap und Hashtable in Java?
Welches ist effizienter in Nicht-Multithread-Anwendungen zu verwenden?
Lösung
Es gibt mehrere Unterschiede zwischen HashMap und HashTable in Java:
Hashtable ist synchronisiert, HashMap jedoch nicht. Dadurch eignet sich HashMap besser für Anwendungen ohne Multithread, da nicht synchronisierte Objekte normalerweise eine bessere Leistung erbringen als synchronisierte Objekte.
Hashtable erlaubt keine Nullwerte und Schlüssel. HashMap erlaubt einen Nullschlüssel und einen NULL-Wert.
Eine Unterklasse von HashMap ist LinkedHashMap. Wenn Sie also die Iterationsreihenfolge (die Standardeinfügereihenfolge) vorhersagen möchten, konvertieren Sie einfach die HashMap in eine LinkedHashMap. Mit Hashtable ist das nicht so einfach.
Da die Synchronisierung für Sie kein Problem darstellt, empfehle ich die Verwendung von HashMap. Wenn die Synchronisierung ein Problem darstellt, können Sie sich auch ConcurrentHashMap ansehen.
5. (Anleitung) Lesen oder Konvertieren eines InputStream in einen String
(1724 Likes)
Wenn Sie ein java.io.InputStream-Objekt haben, z. B. Process dieses Objekt und einen String generieren?
Angenommen, ich habe ein InputStream-Objekt, das Textdaten enthält, und ich möchte es in eine Zeichenfolge konvertieren (zum Beispiel, damit ich den Inhalt des Streams in eine Protokolldatei schreiben kann).
Was ist der einfachste Weg, InputStream in String zu konvertieren?
Lösung
Die Verwendung der Apache Commons IOUtils-Bibliothek zum Kopieren von InputStream in StringWriter ist eine gute Möglichkeit, ähnlich wie diese:
StringWriter writer = new StringWriter(); IOUtils.copy(inputStream, writer, encoding); String theString = writer.toString();
Sogar
// NB: does not close inputStream, you can use IOUtils.closeQuietly for that // 注意:不关闭inputStream,你可以使用 IOUtils.closeQuietly String theString = IOUtils.toString(inputStream, encoding);
Wenn Sie Stream und Writer nicht mischen möchten, können Sie ByteArrayOutputStream verwenden.
6. Warum verwendet das Passwort in Java lieber char[] anstelle von String?
(1574 Likes)
在Swing中,密码字段有一个getPassword()(返回 char数组)方法而不是通常的getText()(返回String)方法。同样的,我遇到过一个建议,不要使用 String 来处理密码。
为什么String涉及到密码时,它就成了一个安全威胁?感觉使用char数组不太方便。
解决方案
String是不可变的。这意味着一旦创建了字符串,如果另一个进程可以进行内存转储,在GC发生前,(除了反射)没有方法可以清除字符串数据。
使用数组操作完之后,可以显式地清除数据:可以给数组赋任何值,密码也不会存在系统中,甚至垃圾回收之前也是如此。
所以,是的,这是一个安全问题 – 但是即使使用了char数组,仅仅缩小了了攻击者有机会获得密码的窗口,它值针对制定的攻击类型。
7、遍历HashMap的最佳方法
(1504个赞)
遍历HashMap中元素的最佳方法是什么?
解决方案
这样遍历entrySet:
public static void printMap(Map mp) { Iterator it = mp.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry)it.next(); System.out.println(pair.getKey() + " = " + pair.getValue()); it.remove(); // avoids a ConcurrentModificationException } }
更多请查阅Map。
8、(如何)从数组创建ArrayList
(1468个赞)
我有一个数组,初始化如下:
Element[] array = {new Element(1), new Element(2), new Element(3)};
我希望将这个数组转化成一个ArrayList类的对象。
解决方案
new ArrayList<Element>(Arrays.asList(array))
9、产生一个Java的内存泄露
(1478个赞)
我有过一个面试,被问到如何产生一个Java内存泄露。不用说,我感到相当傻,甚至如何产生一个的线索都没有。
那么怎么才能产生一个内存泄露呢?
解决方案
在纯Java中,有一个很好的方式可以产生真正的内存泄露(通过执行代码使对象不可访问但仍存在于内存中):
应用产生一个长时间运行的线程(或者使用一个线程池加速泄露)。
线程通过一个(可选的自定义)类加载器加载一个类。
该类分配大内存(例如,new byte[1000000]),赋值给一个强引用存储在静态字段中,再将它自身的引用存储到ThreadLocal中。分配额外的内存是可选的(泄露类实例就够了),但是这样将加速泄露工作。
线程清除所有自定义类的或者类加载器载入的引用。
重复上面步骤。
这样是有效的,因为ThreadLocal持有对象的引用,对象持有类的引用,接着类持有类加载器的引用。反过来,类加载器持有所有已加载类的引用。这会使泄露变得更加严重,因为很多JVM实现的类和类加载都直接从持久带(permgen)分配内存,因而不会被GC回收。
10、使用Java在一个区间内产生随机整数数
(1422个赞)
我试着使用Java生成一个随机整数,但是随机被指定在一个范围里。例如,整数范围是5~10,就是说5是最小的随机值,10是最大的。5到10之间的书也可以是生成的随机数。
解决方案
标准的解决方式(Java1.7 之前)如下:
import java.util.Random; public static int randInt(int min, int max) { Random rand; int randomNum = rand.nextInt((max - min) + 1) + min; return randomNum; }
请查看相关的JavaDoc。在实践中,java.util.Random 类总是优于 java.lang.Math.random()。
特别是当标准库里有一个直接的API来完成这个工作,就没有必要重复制造轮子了。