String 源码分析

String 类代表字符序列,Java 中所有的字符串字面量都作为此类的实例。
String 对象是不可变的,它们的值在创建之后就不能改变,因此 String 是线程安全的。
  • String 的主要属性
    /**
* 用于存储字符的字节数组
*/
@Stable
private final byte[] value; /**
* 用于对 value 字节数组进行编码的编码标识,支持 LATIN1、UTF16
*/
private final byte coder; /** 缓存的哈希值 */
private int hash; // Default to 0 /** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L; /**
* 如果字符串压缩被禁用,则总是使用 UTF16 编码 {@code value} 字节数组。
*
* 是否启用字符串压缩,默认为 true
*/
static final boolean COMPACT_STRINGS; static {
COMPACT_STRINGS = true;
} @Native static final byte LATIN1 = 0;
@Native static final byte UTF16 = 1;
  • String 实例化
    /**
* 创建一个空字符串
*/
public String() {
value = "".value;
coder = "".coder;
} /**
* 基于目标字符数组创建字符串对象
*
* @param value 目标字符数组
*/
public String(char value[]) {
this(value, 0, value.length, null);
} /**
* 基于目标字符数组的子数组创建字符串对象
*
* @param value 源目标字符数组
* @param offset 起始字符索引,从 0 开始
* @param count 连续截取的字符个数
*/
public String(char value[], int offset, int count) {
this(value, offset, count, rangeCheck(value, offset, count));
} /**
* 基于指定字节数组的子数组创建字符串实例
*
* @param bytes 需要解码的字节数组
* @param offset 起始字节索引
* @param length 截取的元素个数
* @param charsetName 字符集名称
*/
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) {
throw new NullPointerException("charsetName");
}
checkBoundsOffCount(offset, length, bytes.length);
// 使用目标字符集解码字节数组
final StringCoding.Result ret =
StringCoding.decode(charsetName, bytes, offset, length);
value = ret.value;
coder = ret.coder;
} /**
* 基于指定字节数组的子数组创建字符串实例
*
* @param bytes 需要解码的字节数组
* @param offset 起始字节索引
* @param length 截取的元素个数
* @param Charset 字符集
*/
public String(byte bytes[], int offset, int length, Charset charset) {
if (charset == null) {
throw new NullPointerException("charset");
}
checkBoundsOffCount(offset, length, bytes.length);
final StringCoding.Result ret =
StringCoding.decode(charset, bytes, offset, length);
value = ret.value;
coder = ret.coder;
} /**
* 基于目标字节数组创建字符串实例。
*
* @param bytes 需要解码的字节数组
* @param charsetName 字符集名称
*/
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
} /**
* 基于目标字节数组创建字符串实例。
*
* @param bytes 需要解码的字节数组
* @param Charset 字符集
*/
public String(byte bytes[], Charset charset) {
this(bytes, 0, bytes.length, charset);
} /**
* 使用平台默认的字符集解码字节数组,创建字符实例
*
* @param bytes 目标字节数组
*/
public String(byte[] bytes) {
this(bytes, 0, bytes.length);
}
  • 返回字符串的长度
    /**
* 返回字符串的长度
*/
@Override
public int length() {
return value.length >> coder();
}
  • 字符串是否为空

/**
* 字符串是否为空
*/
public boolean isEmpty() {
return value.length == 0;
}
  • 获取指定索引处的字符
    /**
* 获取指定索引处的字符
*
* @param index 目标索引
*/
@Override
public char charAt(int index) {
if (isLatin1()) {
return StringLatin1.charAt(value, index);
} else {
return StringUTF16.charAt(value, index);
}
}
  • 读取指定索引处的目标字符的 Unicode 代码点
    /**
* 读取指定索引处的目标字符的 Unicode 代码点
*
* @param index 目标索引
* @return
*/
public int codePointAt(int index) {
if (isLatin1()) {
checkIndex(index, value.length);
return value[index] & 0xff;
}
// UTF16 编码的代码点可能占用多个字节
final int length = value.length >> 1;
checkIndex(index, length);
return StringUTF16.codePointAt(value, index, length);
}
  • 使用指定的字符集将此字符串编码为字节数组并返回
    /**
* 使用指定的字符集将此字符串编码为字节数组并返回。
*
* @param charsetName 目标字符集名称
*/
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) {
throw new NullPointerException();
}
return StringCoding.encode(charsetName, coder(), value);
} /**
* 使用指定的字符集将此字符串编码为字节数组并返回。
*
* @param Charset 目标字符集
*/
public byte[] getBytes(Charset charset) {
if (charset == null) {
throw new NullPointerException();
}
return StringCoding.encode(charset, coder(), value);
}
  • 使用平台默认的字符集将此字符串编码为字节数组并返回
    /**
* 使用平台默认的字符集将此字符串编码为字节数组并返回。
*/
public byte[] getBytes() {
return StringCoding.encode(coder(), value);
}
  • 此字符串的内容是否和目标字符串一致
    /**
* 此字符串的内容是否和目标字符串一致
*/
public boolean contentEquals(CharSequence cs) {
// 参数是一个 StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// 参数是一个 String
if (cs instanceof String) {
return equals(cs);
}
// 参数是一个普通的字符序列 CharSequence
final int n = cs.length();
if (n != length()) {
return false;
}
final byte[] val = value;
if (isLatin1()) {
for (int i = 0; i < n; i++) {
if ((val[i] & 0xff) != cs.charAt(i)) {
return false;
}
}
} else {
if (!StringUTF16.contentEquals(val, cs, n)) {
return false;
}
}
return true;
}
  • 将此字符串和目标字符串进行比较,忽略大小写
    /**
* 将此字符串和目标字符串进行比较,忽略大小写
*/
public boolean equalsIgnoreCase(String anotherString) {
// 先比较长度,再比较内容
return this == anotherString ? true
: anotherString != null
&& anotherString.length() == length()
&& regionMatches(true, 0, anotherString, 0, length());
}
  • 此字符串指定索引开始的子字符串是否以 prefix 开头
    /**
* 此字符串指定索引开始的子字符串是否以 prefix 开头
*
* @param prefix 前缀
* @param toffset 起始索引
*/
public boolean startsWith(String prefix, int toffset) {
// Note: toffset might be near -1>>>1.
if (toffset < 0 || toffset > length() - prefix.length()) {
return false;
}
final byte ta[] = value;
final byte pa[] = prefix.value;
int po = 0;
final int pc = pa.length;
if (coder() == prefix.coder()) {
int to = isLatin1() ? toffset : toffset << 1;
while (po < pc) {
if (ta[to++] != pa[po++]) {
return false;
}
}
} else {
if (isLatin1()) { // && pcoder == UTF16
return false;
}
// coder == UTF16 && pcoder == LATIN1)
while (po < pc) {
if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) {
return false;
}
}
}
return true;
}
  • 此字符串是否以指定的前缀开头
    /**
* 此字符串是否以指定的前缀开头
*
* @param prefix 目标前缀
*/
public boolean startsWith(String prefix) {
return startsWith(prefix, 0);
}
  • 此字符串是否以指定的后缀结尾
    /**
* 此字符串是否以指定的后缀结尾
*
* @param suffix 目标后缀
*/
public boolean endsWith(String suffix) {
return startsWith(suffix, length() - suffix.length());
}
  • 指定字符在此字符串中第一次出现的索引
    /**
* 指定字符在此字符串中第一次出现的索引
*
* @param ch 目标字符
*/
public int indexOf(int ch) {
return indexOf(ch, 0);
} /**
* 从 fromIndex 开始,指定字符在此字符串中第一次出现的索引
*
* @param ch 目标字符
* @param fromIndex 查找的起始索引
*/
public int indexOf(int ch, int fromIndex) {
return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex)
: StringUTF16.indexOf(value, ch, fromIndex);
}
  • 目标字符在此字符串中最后一次出现的索引
    /**
* 目标字符在此字符串中最后一次出现的索引
*
* @param ch 目标字符
*/
public int lastIndexOf(int ch) {
return lastIndexOf(ch, length() - 1);
} /**
* 从 fromIndex 开始,目标字符在此字符串中最后一次出现的索引
*
* @param ch 目标字符
* @param fromIndex 查找的起始索引
*/
public int lastIndexOf(int ch, int fromIndex) {
return isLatin1() ? StringLatin1.lastIndexOf(value, ch, fromIndex)
: StringUTF16.lastIndexOf(value, ch, fromIndex);
}
  • 目标字符串 str 在此字符串中的起始索引
    /**
* 目标字符串 str 在此字符串中的起始索引
*
* @param str 目标字符串
*/
public int indexOf(String str) {
if (coder() == str.coder()) {
return isLatin1() ? StringLatin1.indexOf(value, str.value)
: StringUTF16.indexOf(value, str.value);
}
if (coder() == LATIN1) { // str.coder == UTF16
return -1;
}
return StringUTF16.indexOfLatin1(value, str.value);
} /**
* 从起始索引 fromIndex 开始,目标字符串 str 在此字符串中的起始索引
*
* @param str 目标字符串
* @param fromIndex 查找的起始索引
*/
public int indexOf(String str, int fromIndex) {
return indexOf(value, coder(), length(), str, fromIndex);
}
  • 目标字符串 str 在此字符串中最后一次出现的索引
    /**
* 目标字符串 str 在此字符串中最后一次出现的索引
*
* @param str 目标字符串
*/
public int lastIndexOf(String str) {
return lastIndexOf(str, length());
} /**
* 从起始索引 fromIndex 开始,目标字符串 str 在此字符串中最后一次出现的索引
*
* @param str 目标字符串
* @param fromIndex 查找的起始索引
*/
public int lastIndexOf(String str, int fromIndex) {
return lastIndexOf(value, coder(), length(), str, fromIndex);
}
  • 截取此字符串指定索引 beginIndex 处开始到尾部的子字符串
    /**
* 截取此字符串指定索引 beginIndex 处开始到尾部的子字符串
*
* @param beginIndex 截取的起始索引
*/
public String substring(int beginIndex) {
// 1)起始索引为负数
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
final int subLen = length() - beginIndex;
// 2)起始索引超出最大索引
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
// 3)起始索引为 0
if (beginIndex == 0) {
return this;
}
// 4)截取子字符串
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
}
  • 截取起始索引和结束索引之间的子字符串,包括起始索引,但不包括结束索引
    /**
* 截取起始索引 beginIndex 和结束索引 endIndex 之间的子字符串,包括起始索引,但不包括结束索引
*
* @param beginIndex 起始索引【包含】
* @param endIndex 结束索引【不包含】
*/
public String substring(int beginIndex, int endIndex) {
final int length = length();
// 1)索引非法
checkBoundsBeginEnd(beginIndex, endIndex, length);
final int subLen = endIndex - beginIndex;
// 2)特殊情况
if (beginIndex == 0 && endIndex == length) {
return this;
}
// 3)截取子字符串
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
}
  • 将目标字符串 str 连接到此字符串的尾部
    /**
* 将目标字符串 str 连接到此字符串的尾部
*
* @param str 目标字符串
*/
public String concat(String str) {
final int olen = str.length();
// 1)目标字符串为空
if (olen == 0) {
return this;
}
// 2)编码方式相同,则直接进行字符数组拷贝
if (coder() == str.coder()) {
final byte[] val = value;
final byte[] oval = str.value;
final int len = val.length + oval.length;
final byte[] buf = Arrays.copyOf(val, len);
System.arraycopy(oval, 0, buf, val.length, oval.length);
return new String(buf, coder);
}
// 3)将两个字符解码并拷贝到目标字节数组中
final int len = length();
final byte[] buf = StringUTF16.newBytesFor(len + olen);
getBytes(buf, 0, UTF16);
str.getBytes(buf, len, UTF16);
return new String(buf, UTF16);
}
  • 将此字符串中所有的 oldChar 字符,替换为 newChar 字符
    /**
* 将此字符串中所有的 oldChar 字符,替换为 newChar 字符
*
* @param oldChar 旧字符
* @param newChar 新字符
*/
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
final String ret = isLatin1() ? StringLatin1.replace(value, oldChar, newChar)
: StringUTF16.replace(value, oldChar, newChar);
if (ret != null) {
return ret;
}
}
return this;
}
  • 此字符串是否匹配目标正则表达式 regex
    /**
* 此字符串是否匹配目标正则表达式 regex
*
* @param regex 目标正则表达式
*/
public boolean matches(String regex) {
return Pattern.matches(regex, this);
}
  • 此字符串是否包含目标字符序列 s
    /**
* 此字符串是否包含目标字符序列 s
*
* @param s 待搜索的目标字符序列
*/
public boolean contains(CharSequence s) {
return indexOf(s.toString()) >= 0;
}
  • 将第一个匹配指定正则表达式 regex 的子字符串替换为 replacement
    /**
* 将第一个匹配指定正则表达式 regex 的子字符串替换为 replacement
*
* @param regex 目标正则表达式
* @param replacement 替换字符串
*/
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}
  • 将所有匹配指定正则表达式 regex 的子字符串替换为 replacement
    /**
* 将所有匹配指定正则表达式 regex 的子字符串替换为 replacement
*
* @param regex 目标正则表达式
* @param replacement 替换字符串
*/
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
  • 将此字符串中所有的子字符串 target 替换为目标字符串 replacement
    /**
* 将此字符串中所有的子字符串 target 替换为目标字符串 replacement
*
* @param target 待替换字符串
* @param replacement 替换字符串
*/
public String replace(CharSequence target, CharSequence replacement) {
final String tgtStr = target.toString();
final String replStr = replacement.toString();
int j = indexOf(tgtStr);
if (j < 0) {
return this;
}
final int tgtLen = tgtStr.length();
final int tgtLen1 = Math.max(tgtLen, 1);
final int thisLen = length(); final int newLenHint = thisLen - tgtLen + replStr.length();
if (newLenHint < 0) {
throw new OutOfMemoryError();
}
final StringBuilder sb = new StringBuilder(newLenHint);
int i = 0;
do {
sb.append(this, i, j).append(replStr);
i = j + tgtLen;
} while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
return sb.append(this, i, thisLen).toString();
}
  • 使用指定的正则表达式 regex 将此字符串分割为字符串数组
    /**
* 使用指定的正则表达式 regex 将此字符串分割为字符串数组
*
* @param regex 目标正则表达式
* @param limit 字符串数组的最大长度
*/
public String[] split(String regex, int limit) {
/* fastpath if the regex is a
(1)one-char String and this character is not one of the
RegEx's meta characters ".$|()[{^?*+\\", or
(2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter.
*/
char ch = 0;
if ((regex.length() == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1 ||
regex.length() == 2 &&
regex.charAt(0) == '\\' &&
((ch = regex.charAt(1))-'0'|'9'-ch) < 0 &&
(ch-'a'|'z'-ch) < 0 &&
(ch-'A'|'Z'-ch) < 0) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
final boolean limited = limit > 0;
final ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
final int last = length();
list.add(substring(off, last));
off = last;
break;
}
}
// If no match was found, return this
if (off == 0) {
return new String[]{this};
} // Add remaining segment
if (!limited || list.size() < limit) {
list.add(substring(off, length()));
} // Construct result
int resultSize = list.size();
if (limit == 0) {
while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
resultSize--;
}
}
final String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
return Pattern.compile(regex).split(this, limit);
} /**
* 使用指定的正则表达式 regex 将此字符串分割为字符串数组
*
* @param regex 目标正则表达式
*/
public String[] split(String regex) {
return split(regex, 0);
}
  • 使用指定的连接符 delimiter 顺序连接可变目标字符序列数组 elements 的所有元素
    /**
* 使用指定的连接符 delimiter 顺序连接可变目标字符序列数组 elements 的所有元素
*/
public static String join(CharSequence delimiter, CharSequence... elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
// Number of elements not likely worth Arrays.stream overhead.
final StringJoiner joiner = new StringJoiner(delimiter);
for (final CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
  • 使用指定的连接符 delimiter 顺序连接迭代器中的所有字符序列
    /**
* 使用指定的连接符 delimiter 顺序连接迭代器中的所有字符序列
*/
public static String join(CharSequence delimiter,
Iterable<? extends CharSequence> elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
final StringJoiner joiner = new StringJoiner(delimiter);
for (final CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
  • 使用指定的区域将此字符串的所有字符都转换为小写字符
    /**
* 使用指定的区域将此字符串的所有字符都转换为小写字符
*
* @param locale 目标区域
*/
public String toLowerCase(Locale locale) {
return isLatin1() ? StringLatin1.toLowerCase(this, value, locale)
: StringUTF16.toLowerCase(this, value, locale);
} /**
* 使用默认的区域将此字符串的所有字符都转换为小写字符
*/
public String toLowerCase() {
return toLowerCase(Locale.getDefault());
}
  • 使用指定的区域将此字符串的所有字符都转换为大写字符
    /**
* 使用指定的区域将此字符串的所有字符都转换为大写字符
*
* @param locale 目标区域
*/
public String toUpperCase(Locale locale) {
return isLatin1() ? StringLatin1.toUpperCase(this, value, locale)
: StringUTF16.toUpperCase(this, value, locale);
} /**
* 使用默认的区域将此字符串的所有字符都转换为大写字符
*/
public String toUpperCase() {
return toUpperCase(Locale.getDefault());
}
  • 移除此字符串前后的所有空白符
    /**
* 移除此字符串前后的所有空白符
*/
public String trim() {
final String ret = isLatin1() ? StringLatin1.trim(value)
: StringUTF16.trim(value);
return ret == null ? this : ret;
}
  • 基于此字符串的所有字符创建整形流
    /**
* 基于此字符串的所有字符创建整形流
* @since 9
*/
@Override
public IntStream chars() {
return StreamSupport.intStream(
isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
: new StringUTF16.CharsSpliterator(value, Spliterator.IMMUTABLE),
false);
}
  • 基于此字符串的所有 Unicode 代码点创建整形流
    /**
* 基于此字符串的所有 Unicode 代码点创建整形流
* @since 9
*/
@Override
public IntStream codePoints() {
return StreamSupport.intStream(
isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
: new StringUTF16.CodePointsSpliterator(value, Spliterator.IMMUTABLE),
false);
}
  • 将此字符串转换为字符数组
    /**
* 将此字符串转换为字符数组
*/
public char[] toCharArray() {
return isLatin1() ? StringLatin1.toChars(value)
: StringUTF16.toChars(value);
}
  • 使用指定的参数列表 args 格式化目标字符串 format
    /**
* 使用指定的参数列表 args 格式化目标字符串 format
*/
public static String format(String format, Object... args) {
return new Formatter().format(format, args).toString();
}
  • 将目标对象 obj 转换为字符串
    /**
* 将目标对象 obj 转换为字符串
*
* @param obj 目标对象
*/
public static String valueOf(Object obj) {
return obj == null ? "null" : obj.toString();
}
  • 返回此字符串的规范表示形式,将此字符串加入由 String 类管理的字符串常量池中,所有的字符串字面量和字符串常量都缓存在字符串常量池中。
    public native String intern();

String 类源码分析的更多相关文章

  1. String类源码分析(JDK1.7)

    以下学习根据JDK1.7String类源代码做注释 public final class String implements java.io.Serializable, Comparable<S ...

  2. String类源码分析

    1.String类注释说明 /** * The {@code String} class represents character strings. All * string literals in ...

  3. List 接口以及实现类和相关类源码分析

    List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...

  4. Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析

    上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...

  5. Java Properties类源码分析

    一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...

  6. java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析

    java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...

  7. Java并发编程笔记之Unsafe类和LockSupport类源码分析

    一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...

  8. Cocos2d-X3.0 刨根问底(三)----- Director类源码分析

    上一章我们完整的跟了一遍HelloWorld的源码,了解了Cocos2d-x的启动流程.其中Director这个类贯穿了整个Application程序,这章随小鱼一起把这个类分析透彻. 小鱼的阅读源码 ...

  9. java.lang.String 类源码解读

    String类定义实现了java.io.Serializable, Comparable<String>, CharSequence 三个接口:并且为final修饰. public fin ...

随机推荐

  1. 11、find查找

    1.find查找概述 为什么要有文件查找,因为很多时候我们可能会忘了某个文件所在的位置,此时就需要通过find来查找. find命令可以根据不同的条件来进行查找文件,例如:文件名称.文件大小.文件修改 ...

  2. JavaWeb零基础入门-02 开发环境安装

    大家好!我又来了,上一篇我们讲了一些基础概念:Html.Web服务器.数据库.Http和JavaWeb三大组件,它们是什么,有什么作用,都有了初步的了解.接下来我们进入学习JavaWeb的第一步,开发 ...

  3. 跟着动画来学习TCP三次握手和四次挥手

    TCP三次握手和四次挥手的问题在面试中是最为常见的考点之一.很多读者都知道三次和四次,但是如果问深入一点,他们往往都无法作出准确回答. 点我查看如何应对面试中的三次握手.四次挥手 本篇尝试使用动画来对 ...

  4. cmd拷贝文件夹时,处理提示

    xcopy 若目标盘上不存在此子目录,而在目标盘的结束符又不以"\"为结束,则将提示: does destination specify a file name or direct ...

  5. CPU性能指标

    1,主频 主频 = 时钟频率,它是指CPU内部晶振的频率,常用单位为MHz,它反映了CPU的基本工作节拍; 时钟频率又称主频,它是指CPU内部晶振的频率,常用单位为MHz,它反映了CPU的基本工作节拍 ...

  6. 校验 url 是否以http 或者https 开头

    var reUrl01 = /^((ht|f)tps?):\/\/([\w-]+(\.[\w-]+)*\/?)+(\?([\w\-\.,@?^=%&:\/~\+#]*)+)?$/; var r ...

  7. mybatis之联表查询

    今天碰到了一个问题,就是要在三张表里面各取一部分数据然后组成一个list传到前台页面显示.但是并不想在后台做太多判断,(因为涉及到for循环)会拉慢运行速度.正好用的框架是spring+springM ...

  8. 绑定与非绑定以及property装饰器_day_21 作业题

    1.定义MySQL类 1.对象有id.host.port三个属性 2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一 3.提供两种实例化方式,方式一:用户传入host和po ...

  9. UVA 10900 So do you want to be a 2^n-aire?

    #include<bits/stdc++.h> #include<stdio.h> #include<iostream> #include<cmath> ...

  10. [洛谷P5361][SDOI2019]热闹又尴尬的聚会:构造题

    分析 构造方法 (截图自UOJ群) 可以使用std::set维护这个过程,不过据说可以做到\(O(n+m)\).. 正确性证明 题目中的要求等价于\((p+1)(q+1) > n\) 设每次找出 ...