Java - 常见问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/169815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:16:45  来源:igfitidea点击:

Java - Common Gotchas

java

提问by Alan

In the same spirit of other platforms, it seemed logical to follow up with this question: What are common non-obvious mistakes in Java? Things that seem like they ought to work, but don't.

本着与其他平台相同的精神,跟进这个问题似乎是合乎逻辑的:Java 中有哪些常见的非明显错误?看起来应该起作用的事情,但没有。

I won't give guidelines as to how to structure answers, or what's "too easy" to be considered a gotcha, since that's what the voting is for.

我不会给出关于如何构建答案的指导方针,或者什么是“太容易”而不能被认为是一个问题,因为这就是投票的目的。

See also:

也可以看看:

回答by butterchicken

"a,b,c,d,,,".split(",").length

returns 4, not7 as you might (and I certainly did) expect. splitignores all trailing empty Strings returned. That means:

返回 4,而不是您可能(我当然确实如此)期望的 7。split忽略返回的所有尾随空字符串。这意味着:

",,,a,b,c,d".split(",").length

returns 7! To get what I would think of as the "least astonishing" behaviour, you need to do something quite astonishing:

返回 7!要获得我认为的“最不令人惊讶”的行为,您需要做一些非常令人惊讶的事情:

"a,b,c,d,,,".split(",",-1).length

to get 7.

得到 7。

回答by David

Comparing equality of objects using ==instead of .equals()-- which behaves completely differently for primitives.

使用==而不是比较对象的相等性.equals()——这对于基元的行为完全不同。

This gotcha ensures newcomers are befuddled when "foo" == "foo"but new String("foo") != new String("foo").

这个问题确保新人在"foo" == "foo"但是时会感到困惑new String("foo") != new String("foo")

回答by oxbow_lakes

I think a very sneaky one is the String.substringmethod. This re-uses the same underlying char[]array as the original string with a different offsetand length.

我认为一个非常狡猾的String.substring方法是。这会重新使用与char[]原始字符串相同的底层数组,并带有不同的offsetlength

This can lead to very hard-to-see memory problems. For example, you may be parsing extremely large files (XMLperhaps) for a few small bits. If you have converted the whole file to a String(rather than used a Readerto "walk" over the file) and use substringto grab the bits you want, you are still carrying around the full file-sized char[]array behind the scenes. I have seen this happen a number of times and it can be very difficult to spot.

这会导致非常难以察觉的内存问题。例如,您可能正在解析极大文件(XML可能)的几个小部分。如果您已将整个文件转换为 a String(而不是使用 aReader来“遍历”文件)并用于substring抓取所需的位,那么您仍在char[]幕后携带完整的文件大小的数组。我已经多次看到这种情况发生,而且很难发现。

In fact this is a perfect example of why interfacecan never be fully separated from implementation. And it was a perfect introduction (for me) a number of years ago as to why you should be suspicious of the quality of 3rd party code.

事实上,这是一个完美的例子,说明了为什么接口永远不能与实现完全分离。这是几年前(对我而言)一个完美的介绍,说明为什么您应该怀疑 3rd 方代码的质量。

回答by extraneon

Overriding equals() but not hashCode()

覆盖 equals() 但不覆盖 hashCode()

It can have really unexpected results when using maps, sets or lists.

在使用地图、集合或列表时,它可能会产生真正意想不到的结果。

回答by extraneon

SimpleDateFormat is not thread safe.

SimpleDateFormat 不是线程安全的。

回答by MBCook

There are two that annoy me quite a bit.

有两个让我很恼火。

Date/Calendar

日期/日历

First, the Java Date and Calendar classes are seriously messed up. I know there are proposals to fix them, I just hope they succeed.

首先,Java Date 和 Calendar 类严重混乱。我知道有一些建议可以解决它们,我只希望它们能成功。

Calendar.get(Calendar.DAY_OF_MONTH) is 1-based
Calendar.get(Calendar.MONTH) is 0-based

Calendar.get(Calendar.DAY_OF_MONTH) 是基于 1 的
Calendar.get(Calendar.MONTH) 是基于 0 的

Auto-boxing preventing thinking

自动拳击防止思考

The other one is Integer vs int (this goes for any primitive version of an object). This is specifically an annoyance caused by not thinking of Integer as different from int (since you can treat them the same much of the time due to auto-boxing).

另一个是整数与整数(这适用于对象的任何原始版本)。这特别是由于不认为 Integer 与 int 不同而引起的烦恼(因为由于自动装箱,您可以在很多时候将它们视为相同)。

int x = 5;
int y = 5;
Integer z = new Integer(5);
Integer t = new Integer(5);

System.out.println(5 == x);     // Prints true
System.out.println(x == y);     // Prints true
System.out.println(x == z);     // Prints true (auto-boxing can be so nice)
System.out.println(5 == z);     // Prints true
System.out.println(z == t);     // Prints SOMETHING

Since z and t are objects, even they though hold the same value, they are (most likely) different objects. What you really meant is:

由于 z 和 t 是对象,即使它们具有相同的值,它们(很可能)也是不同的对象。你真正的意思是:

System.out.println(z.equals(t));   // Prints true

This one can be a pain to track down. You go debugging something, everything looks fine, and you finally end up finding that your problem is that 5 != 5 when both are objects.

这可能很难追踪。你去调试一些东西,一切看起来都很好,你最终发现你的问题是 5 != 5 当两者都是对象时。

Being able to say

能够说

List<Integer> stuff = new ArrayList<Integer>();

stuff.add(5);

is sonice. It made Java so much more usable to not have to put all those "new Integer(5)"s and "((Integer) list.get(3)).intValue()" lines all over the place. But those benefits come with this gotcha.

这么好看。它使 Java 变得更加有用,不必将所有那些“new Integer(5)”和“((Integer) list.get(3)).intValue()”行放在所有地方。但是这些好处伴随着这个问题。

回答by David Plumpton

Try reading Java Puzzlerswhich is full of scary stuff, even if much of it is not stuff you bump into every day. But it will destroy much of your confidence in the language.

尝试阅读Java Puzzlers,其中充满了可怕的东西,即使其中大部分内容不是您每天都会碰到的东西。但它会摧毁你对语言的大部分信心。

回答by Tom Hawtin - tackline

List<Integer> list = new java.util.ArrayList<Integer>();
list.add(1);
list.remove(1); // throws...

The old APIs were not designed with boxing in mind, so overload with primitives and objects.

旧的 API 的设计没有考虑到装箱,所以原始和对象过载。

回答by Claudiu

This one I just came across:

我刚刚遇到的这个:

double[] aList = new double[400];

List l = Arrays.asList(aList);
//do intense stuff with l

Anyone see the problem?

有人看到问题了吗?



What happens is, Arrays.asList()expects an array of object types (Double[], for example). It'd be nice if it just threw an error for the previous ocde. However, asList()can also take arguments like so:

发生的情况是,Arrays.asList()需要一个对象类型数组(例如,Double[])。如果它只是为之前的 ocde 抛出一个错误,那就太好了。但是,asList()也可以采用如下参数:

Arrays.asList(1, 9, 4, 4, 20);

So what the code does is create a Listwith one element - a double[].

所以代码所做的是List用一个元素创建一个- a double[]

I should've figured when it took 0ms to sort a 750000 element array...

我应该知道什么时候对 750000 个元素的数组进行排序需要 0 毫秒...

回答by John Nilsson

Floats

浮动

I don't know many times I've seen

我不知道我见过多少次

floata == floatb

where the "correct" test should be

“正确”测试应该在哪里

Math.abs(floata - floatb) < 0.001

I really wish BigDecimal with a literal syntax was the default decimal type...

我真的希望带有文字语法的 BigDecimal 是默认的十进制类型......