Stack Overflow 上人气爆表的10个 Java 问题

一、 为何两个(1927年)时间相减获得一个奇怪的结果?

(3623个赞)html

若是执行下面的程序,程序解析两个间隔1秒的日期字符串并比较:java

1
2
3
4
5
6
7
8
9
10
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);
}

输出是:面试

1
353

为何 ld4-ld3 不是1(由于我但愿这两个时间差是一秒),而是353?apache

若是将日期字符串各加一秒:api

1
2
String str3 = "1927-12-31 23:54:08"
String str4 = "1927-12-31 23:54:09" ;

ld4-ld3 的结果是1.数组

1
2
3
4
5
6
7
sun.util.calendar.ZoneInfo[ id = "Asia/Shanghai" ,
offset=28800000,dstSavings=0,
useDaylight= false ,
transitions=19,
lastRule=null]
 
Locale(Locale.getDefault()): zh_CN

解决方案安全

这是上海时区在12月31日有一个变化。多线程

查阅这个网址来了解上海在1927年时区变化的细节。基本上在1927年年末的午夜,始终会回拨5分52秒。因此“1927-12-31 23:54:08”实际上发生了两次,看起来Java解析了后一次的时间做为当地的日期和时间致使了差别。oracle

二、Java是“引用传递”仍是“值传递”?

(2480个赞)dom

我一直认为Java是引用传递;然而,我看了一堆博客(例如这篇)声称不是这样的。我认为我没有理解它们之间的区别。

给个解释?

解决方案

Java一直是值传递。不幸的是,他们决定把指针叫作引用,所以新人老是被搞晕。由于这些引用也是经过值传递的。

三、一个关于Java += 操做符的问题

(2223赞)

直到今天我认为这个例子:

1
i += j;

只是一个简写的:

1
i = i + j;

但若是这样作:

1
2
int i = 5 ;
long j = 8 ;

然而 i = i + j; 无法编译,而 i += j; 就能够编译。

这意味着i += j; 其实是i = (type of i) (i + j)的简写么?

解决方案

总有人问这类问题,JLS里有答案。参见 §15.26.2复合赋值运算符。摘录:

E1 op= E2 型的复合赋值表达式等价于 E1 = (T)((E1) op (E2)),这里 T 是 E1 的类型,不一样的是 E1 只计算一次。

一个例子,引自 §15.26.2

[...] 下面的代码是正确的:

1
2
short x = 3 ;
x += 4.6 ;

x的结果等于7,由于它等价于:

1
2
short x = 3 ;
x = ( short )(x + 4.6 );

换句话说,你的假设是正确的。

四、HashMap 和 Hashtable 之间的不一样?

(1769个赞)

Java中 HashMap 和 Hashtable的不一样是什么?

非多线程应用中使用哪一个更有效率?

解决方案

Java 中 HashMap 和 HashTable 有几个不一样点:

  1. Hashtable 是同步的,然而 HashMap不是。 这使得HashMap更适合非线程应用,由于非同步对象一般执行效率优于同步对象。

  2. Hashtable 不容许 null 值和键。HashMap容许有一个 null 键和人一个 NULL 值。

  3. HashMap的一个子类是LinkedHashMap。因此,若是想预知迭代顺序(默认的插入顺序),只需将HashMap转换成一个LinkedHashMap。用Hashtable就不会这么简单。

由于同步对你来讲不是个问题,我推荐使用HashMap。若是同步成为问题,你可能还要看看ConcurrentHashMap

五、(如何) 读取或者把一个 InputStream 转成一个 String

(1724个赞)

若是你有一个 java.io.InputStream 对象,如处理这个对象并生成一个字符串?

假定我有一个 InputStream 对象,它包含文本数据,我但愿将它转化成一个字符串(例如,这样我能够将流的内容写到一个log文件中)。

InputStream 转化成 String 最简单方法是什么?

解决方案

使用 Apache commons IOUtils库来拷贝InputStream到StringWriter是一种不错的方式,相似这样:

1
2
3
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();

甚至

1
2
3
// NB: does not close inputStream, you can use IOUtils.closeQuietly for that
// 注意:不关闭inputStream,你可使用 IOUtils.closeQuietly
String theString = IOUtils.toString(inputStream, encoding);

或者,若是不想混合Stream和Writer,可使用 ByteArrayOutputStream。

六、为何Java中的密码优先使用 char[] 而不是String?

(1574个赞)

在Swing中,密码字段有一个getPassword()(返回 char数组)方法而不是一般的getText()(返回String)方法。一样的,我遇到过一个建议,不要使用 String 来处理密码。

为何String涉及到密码时,它就成了一个安全威胁?感受使用char数组不太方便。

解决方案

String是不可变的。这意味着一旦建立了字符串,若是另外一个进程能够进行内存转储,在GC发生前,(除了反射)没有方法能够清除字符串数据。

使用数组操做完以后,能够显式地清除数据:能够给数组赋任何值,密码也不会存在系统中,甚至垃圾回收以前也是如此。

因此,是的,这是一个安全问题 – 可是即便使用了char数组,仅仅缩小了了攻击者有机会得到密码的窗口,它值针对制定的攻击类型。

七、遍历HashMap的最佳方法

(1504个赞)

遍历HashMap中元素的最佳方法是什么?

解决方案

这样遍历entrySet

1
2
3
4
5
6
7
8
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

八、(如何)从数组建立ArrayList

(1468个赞)

我有一个数组,初始化以下:

1
Element[] array = { new Element( 1 ), new Element( 2 ), new Element( 3 )};

我但愿将这个数组转化成一个ArrayList类的对象。

解决方案

1
new ArrayList<Element>(Arrays.asList(array))

九、产生一个Java的内存泄露

(1478个赞)

我有过一个面试,被问到如何产生一个Java内存泄露。不用说,我感到至关傻,甚至如何产生一个的线索都没有。

那么怎么才能产生一个内存泄露呢?

解决方案

在纯Java中,有一个很好的方式能够产生真正的内存泄露(经过执行代码使对象不可访问但仍存在于内存中):

  1. 应用产生一个长时间运行的线程(或者使用一个线程池加速泄露)。

  2. 线程经过一个(可选的自定义)类加载器加载一个类。

  3. 该类分配大内存(例如,new byte[1000000]),赋值给一个强引用存储在静态字段中,再将它自身的引用存储到ThreadLocal中。分配额外的内存是可选的(泄露类实例就够了),可是这样将加速泄露工做。

  4. 线程清除全部自定义类的或者类加载器载入的引用。

  5. 重复上面步骤。

这样是有效的,由于ThreadLocal持有对象的引用,对象持有类的引用,接着类持有类加载器的引用。反过来,类加载器持有全部已加载类的引用。这会使泄露变得更加严重,由于不少JVM实现的类和类加载都直接从持久带(permgen)分配内存,于是不会被GC回收。

十、使用Java在一个区间内产生随机整数数

(1422个赞)

我试着使用Java生成一个随机整数,可是随机被指定在一个范围里。例如,整数范围是5~10,就是说5是最小的随机值,10是最大的。5到10之间的书也能够是生成的随机数。

解决方案

标准的解决方式(Java1.7 以前)以下:

1
2
3
4
5
6
7
8
9
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来完成这个工做,就没有必要重复制造轮子了。

原文连接: nolsit 翻译: ImportNew.com liken
译文连接: http://www.importnew.com/16841.html
转载请保留原文出处、译者和译文连接。]

相关文章
相关标签/搜索