情况:有一个Java ESB,它从Vaadin Web表单中获取输入(系列名称),并应保证在将其保存到DB之前对其进行上限。
我被分配调查报告的问题,小写字符有时会出现在数据库中。我了解到,程序在通过EntityManager保存数据之前使用 String.toUpperCase()(它是唯一修改接收数据的地方)。
所以我想知道的是,这是否足够。到目前为止,我还没有发现任何"着名的"与 toUpperCase()功能相关的问题,但我想确定。
所以问题 - String.toUpperCase()总能完成它的工作吗?或者是否有任何可能出现错误的字符或情况且字母可能不是大写字母?
答案 0 :(得分:2)
Java String.toUpperCase()是否会失败?
这取决于您是否传递区域敏感字符串(见下文)。
在Java.lang.String
的实现中,它只使用默认语言环境:
public String toUpperCase() {
return toUpperCase(Locale.getDefault());
}
toUpperCase(Locale)使用给定Locale的规则将此String中的所有字符转换为大写。案例映射基于Character类指定的Unicode标准版本。由于大小写映射并不总是1:1的char映射,因此生成的String可能与原始String的 长度 不同。
此方法 区域设置敏感 ,如果用于要独立解释区域设置的字符串,则可能会产生意外结果。例如,编程语言标识符,协议密钥和HTML标记。
要获取区域设置不敏感字符串的正确结果,请使用toUpperCase(Locale.ENGLISH)。
如果您对如何实施 toUpperCase(Locale)感兴趣:
public String toUpperCase(Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int firstLower;
final int len = value.length;
/* Now check if there are any characters that need to be changed. */
scan: {
for (firstLower = 0 ; firstLower < len; ) {
int c = (int)value[firstLower];
int srcCount;
if ((c >= Character.MIN_HIGH_SURROGATE)
&& (c <= Character.MAX_HIGH_SURROGATE)) {
c = codePointAt(firstLower);
srcCount = Character.charCount(c);
} else {
srcCount = 1;
}
int upperCaseChar = Character.toUpperCaseEx(c);
if ((upperCaseChar == Character.ERROR)
|| (c != upperCaseChar)) {
break scan;
}
firstLower += srcCount;
}
return this;
}
/* result may grow, so i+resultOffset is the write location in result */
int resultOffset = 0;
char[] result = new char[len]; /* may grow */
/* Just copy the first few upperCase characters. */
System.arraycopy(value, 0, result, 0, firstLower);
String lang = locale.getLanguage();
boolean localeDependent =
(lang == "tr" || lang == "az" || lang == "lt");
char[] upperCharArray;
int upperChar;
int srcChar;
int srcCount;
for (int i = firstLower; i < len; i += srcCount) {
srcChar = (int)value[i];
if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
(char)srcChar <= Character.MAX_HIGH_SURROGATE) {
srcChar = codePointAt(i);
srcCount = Character.charCount(srcChar);
} else {
srcCount = 1;
}
if (localeDependent) {
upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
} else {
upperChar = Character.toUpperCaseEx(srcChar);
}
if ((upperChar == Character.ERROR)
|| (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
if (upperChar == Character.ERROR) {
if (localeDependent) {
upperCharArray =
ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
} else {
upperCharArray = Character.toUpperCaseCharArray(srcChar);
}
} else if (srcCount == 2) {
resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;
continue;
} else {
upperCharArray = Character.toChars(upperChar);
}
/* Grow result if needed */
int mapLen = upperCharArray.length;
if (mapLen > srcCount) {
char[] result2 = new char[result.length + mapLen - srcCount];
System.arraycopy(result, 0, result2, 0, i + resultOffset);
result = result2;
}
for (int x = 0; x < mapLen; ++x) {
result[i + resultOffset + x] = upperCharArray[x];
}
resultOffset += (mapLen - srcCount);
} else {
result[i + resultOffset] = (char)upperChar;
}
}
return new String(result, 0, len + resultOffset);
}
答案 1 :(得分:1)
如果没有任何进一步的信息(你决定小写)存储在数据库中我会猜测原点类似于那些博客中解释的案例
作者:Heinz Kabutz
http://www.javaspecialists.eu/archive/Issue209.html
http://www.javaspecialists.eu/archive/Issue211.html
编辑可能在数据库中存储的字符看起来与拉丁字符相似(基于字体),并且不存在大写字母。
一个例子是GREEK LETTER YOT
,它看起来与LATIN SMALL LETTER J
类似,没有大写字母。
用于演示的小片段。
int[] codePoints = { 0x03F3, 0x006A};
for (int codePoint : codePoints) {
char lowerCase = (char) Character.toLowerCase(codePoint);
char upperCase = (char) Character.toUpperCase(codePoint);
System.out.printf("Unicode name: %s%n", Character.getName(codePoint));
System.out.printf("lowercase : %s%n", lowerCase);
System.out.printf("uppercase : %s (%s)%n", upperCase,
Character.isUpperCase(upperCase));
}
输出
Unicode name: GREEK LETTER YOT
lowercase : ϳ
uppercase : ϳ (false)
Unicode name: LATIN SMALL LETTER J
lowercase : j
uppercase : J (true)