Object类源码
Object是所有类的父类,意味着接下来看的所有的类都会继承或者重写Object类中的方法。逐一看一下Object类中的所有方法。
源码中类的介绍:Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.
本地方法关键字 Native:用于修饰方法,表示该方法不是java编写的,是底层系统语言已经编写好了的,一般是C/C++编写。
在Object类的静态代码块中调用了私有的本地方法。因为被private修饰,说明其他类继承不了,是Object类所特有的,与日常开发无光,不深入去了解。
registerNatives()
,用于注册一组本地方法,这些方法提供了Object
类的基本操作的本地实现。这些本地方法通常是由JVM的实现提供的,用于提高执行效率或与底层系统进行交互。
getclass():返回运行时,实例的类对象。注意泛型擦除。
- 泛型擦除:编译器在编译时会去掉泛型的信息,生成一个桥接方法保持与原方法的兼容性。
-
// 编译前 Pair<String> pair = new Pair<>("Hello", "World"); // 编译后(类型擦除) Pair pair = new Pair("Hello", "World"); // 编译前 class Box<T> { T value; void setValue(T value) { this.value = value; } T getValue() { return value; } } // 编译后(桥接方法) class Box { Object value; void setValue(Object value) { this.value = value; } Object getValue() { return value; } }
hashCode() :返回对象的哈希码值。一般会为不同的对象返回不同的整数。
- Object类的equals()方法默认实现是比较对象的引用地址。
- 当覆盖hashCode方法时需要同时覆盖equals方法。
-
在Java中,
equals
和hashCode
方法之间存在一种约定,这个约定要求相等的对象必须具有相等的哈希码。这是因为在使用一些基于哈希表的数据结构时(例如HashMap
或HashSet
),哈希码用于快速定位对象在内部数据结构中的位置。如果两个对象被认为是相等的(根据
equals
方法的定义),那么它们的哈希码应该相同。因此,如果你覆盖了equals
方法来定义对象的相等性,就需要确保相等的对象产生相同的哈希码。这样的一致性保证了在使用这些对象的哈希值作为键或集合元素时,能够正确地执行哈希表的操作,例如查找、插入和删除。
-
基于hash结构的集合:HashMap、HashSet、Hashtable、LinkedHashMap、ConcurrentHashMap
-
equals():比较对象之间的等价关系。
- Object类的equals()方法默认实现是比较对象的引用地址。
- 当覆盖equals方法时需要同时覆盖hashCode方法。
clone():克隆一个对象
- clone方法执行的是浅拷贝,即它创建了一个新实例并复制了原始对象的字段的内容,但字段中的对象引用仍然指向相同的对象。(说明两个对象会存在共享的部分)
- 深拷贝:它创建一个新的对象,同时递归地复制该对象内部的所有可变对象,而不仅仅是复制引用。深拷贝确保克隆对象和原始对象的内部结构完全独立,对一个对象的修改不会影响到另一个对象。
- 对象的类不实现
Cloneable
接口,调用clone
方法将抛出此异常。子类也可以选择抛出此异常以表示该类的实例无法被克隆。
toString():返回对象的字符串表示形式。
- Object类默认返回类名@16进制的哈希码值。
notify():唤醒等待线程
notifyAll():唤醒所有等待线程
wait():让当前线程进入等待状态
finalize():GC调用,在对象回收之前释放或者清理资源。
String类源码
属性:
-
private final char value[];
- 很多方法操作数组就能获取结果
-
private int hash; // Default to 0
compareToIgnoreCase(String str):忽略大小写比较
静态内部类:CaseInsensitiveComparator实现Comparator接口,用与忽略大小写比较。
public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
// No overflow because of numeric promotion
return c1 - c2;
}
}
}
}
return n1 - n2;
}
构造方法:这些构造方法都会返回一个char 类型的数组,赋值给value。
equals(Object anObject):
先比较引用是否相等,如果相等显然相等。否则比较字符串的每一个字符。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
compareTo(String anotherString) :比较每一个字符
返回:用字符串本身字符减去要比较的字符串字符(参数)
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
toLowerCase():转小写。
为什么其他方法是返回一个char数组赋值给value,而转大小写是new String对象?
修改了原字符串,与原先的字符串值不一样,又因为string 的value被finally修饰,所以只能new一个对象。
public String toLowerCase(Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
......
return new String(result, 0, len + resultOffset);
}
getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
调用本地方法System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);将char数组复制到一个新的数组中。
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
toString()
public String toString() {
return this;
}
//
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
substring(int beginIndex)
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
StringBuilder类源码
StringBuilder继承AbstractStringBuilder
AbstractStringBuilder:
append(String str)
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
// 确保数组容量足够大,不够扩容:长度大小左移一位并加2
ensureCapacityInternal(count + len);
// 将str复制到value,String类源码介绍过
str.getChars(0, len, value, count);
// 得出count其实用于计算char数组长度
count += len;
return this;
}
// 为null char数组赋值null
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
append(StringBuffer sb)
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
}
// AbstractStringBuilder定义了getChars方法,内用与String类的getChars一样,调用native方法
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
if ((srcEnd < 0) || (srcEnd > count))
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
append(boolean b) 、append(Object obj)
public AbstractStringBuilder append(boolean b) {
if (b) {
ensureCapacityInternal(count + 4);
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
} else {
ensureCapacityInternal(count + 5);
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
return this;
}
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
toString() :重写toString方法,返回一个new String对象
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
StringBuffer类源码
StringBuffer与StringBuilder一样都继承AbstractStringBuilder,StringBufferr的方法基本上也是和StringBuilder一样调用父类的方法。