2004年成立,成员为くど(作编曲等)与monet(歌手)两人。最初的作品是2005年同人社团水镜的《灯穗奇谭》OP《under the different sky》,乐队也由此与枕社产生了极强的联系,在松本文纪加入之前一直作为枕的音乐制作主力活跃着。虽然乐队已经停止活动,但直到现在枕社官网在《樱之刻》的音乐一栏依然写着ピクセルビー的名字。
We find, for example, almost everywhere when we are traveling, men who are ready to serve those who pass and have lodgings ready to receive them. We dispose of their services as we wish; we command them and they obey us and make us believe that it gives thempleasure to serve us. They never excuse themselves from rendering any service demanded of them. How could such behavior be more admirable if it were animated by the spirit of charity itself? It is greed which makes them act, and they do so with such good grace that one believes one does them a favor by employing their services. Think how much charity would be required to build a whole house for another man, to furnish it completely and then hand him the key. Greed does this quite joyfully. What a degree of charity would be needed to go search for medicines in the Indies, or abase oneself to the vilest services, and the most painful? Greed does all this without complaining. <span class=”hint–top hint–error hint–medium hint–rounded hint–bounce” aria-label=””De la grandeur,” Jourdain, p. 398. “>[2]
Java’s generics type erasure has been regarded as a failure design since JDK 1.5, but I haven’t realized it until today when I run into a serious issue about it.
The issue
I’m using night-config library to parse TOML config file for my program. I parsed and stored a list of long from TOML. Right after I got my program up and running, I noticed that list.contains(x) failures at random numbers. Those numbers seem to exist in the list and successfully printed out, but I cannot locate the issue based on the information I got.
So I read the TOML parser it self, trying to locate where it handles Integer/Long parsing and found the function that deal with number parsing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// https://github.com/TheElectronWill/night-config/blob/master/toml/src/main/java/com/electronwill/nightconfig/toml/ValueParser.java#L76 privatestatic Number parseNumber(CharsWrapper valueChars) { ... long longValue; try { longValue = Utils.parseLong(numberChars, base); } catch (NumberFormatException ex) { thrownewParsingException("Invalid integer value: " + valueChars); } intintValue= (int)longValue; if (intValue == longValue) { return intValue;// returns an int if it is enough to represent the value correctly } return longValue; }
Note that: returns an int if it is enough to represent the value correctly
So the output list, assumptively ArrayList<Long> typed, does consist both Integer and Long if Integer is enought to represent the value, calling List.contains will certainly fail if you pass a long parameter to check whether the number, which is actually int, is in the collection.
Having it double-checked by using fastutil’s LongArrayList confirmed my thoughts, it fails to construct because there are int values in a marked ArrayList<Long> collection.
Why blame Java’s generic design?
In this case, ArrayList<Long> is merely a mark that give instructions for compiler to check, but it does not replace the Object[] array in the list, nor does it assert runtime type-checking. The issue may absolutely be avoided or easily solved in C#, Rust and other strong-typed generics language.
Solution
Always use strong-typed fastutil or trove collections for storing primitive values.
Blame Java for it’s bad design.
In this case, cast boxed int or long values to Number and cast it back to Long, then store them in a LongArrayList.