一图胜千言,下面图解均来自Program Creek 网站的Java教程
字符串的不变性
- 定义字符串
String s = "abcd";
s持有字符串abcd的引用
2. 用一个字符串变量赋值另一个字符串变量
String s2 = s;
s2和s持有同一个对象的引用
3. 合并字符串
s = s.concat("ef");
总结
一旦在堆内存中创建了字符串,字符串本身是不能改变的,如果要改变通过返回新的字符串对象实现。因此为了避免产生更多的临时变量,消耗垃圾回收机制资源,改变String,尽量使用StringBuilder和StringBuffer类代替String。
Java equals()方法和hashCode()方法的联系
public boolean equals(Object obj)
public int hashCode()
这两个方法是在Java super class “java.lang.Object”中定义的重要方法,
- 如果两个对象相等 那么她们hashCode一定相等
- 如果两个对象hashCode相等,她们两个对象不一定相等
##一个常见的错误
import java.util.HashMap;
public class Apple {
private String color;
public Apple(String color) {
this.color = color;
}
public boolean equals(Object obj) {
if(obj==null) return false;
if (!(obj instanceof Apple))
return false;
if (obj == this)
return true;
return this.color.equals(((Apple) obj).color);
}
public static void main(String[] args) {
Apple a1 = new Apple("green");
Apple a2 = new Apple("red");
//hashMap stores apple type and its quantity
HashMap<Apple, Integer> m = new HashMap<Apple, Integer>();
m.put(a1, 10);
m.put(a2, 20);
System.out.println(m.get(new Apple("green")));
}
}
对象green Apple明明已经被加入到Map中,但是检索Map的时候查找green Apple对象却返回空
问题由于hashCode()引起
因为Apple对象没有实现hashCode方法,在Map中为了去查找一个对象比线性查找更快,通过两个验证的方式查找,如果两个对象的hashCode不相等,就不用再执行它们的equals方法了。
解决上面问题只需要实现他的hashCode方法即可
public int hashCode(){
return this.color.hashCode();
}
Java异常类的继承关系
Java中的异常分为可检测异常和不可预知异常,她们的关系在下表中
红色的为受检查异常,任何受检测异常可以在方法体或者方法定义中抛出。必须在编译期完成。绿色的是不可测异常
Collection和Collections
- 这是两个完全不同的东西。Collection是Collection接口继承关系中的根接口,而Collections是一个包含很多操作集合元素静态方法的类。
- Collection的继承关系
- Map的继承关系
Java同步机制
别名
别名意味着可以为同一块内存区域给予不同的名称,这些名称可以是不同的类型。
B[] b = new B[10];
A[] a = b;
a[0] = new A();
b[0].methodParent();
a、b都指向内存区域,到运行时再确定实际要调用的是谁
class A {
public void methodParent() {
System.out.println("method in Parent");
}
}
class B extends A {
public void methodParent() {
System.out.println("override method in Child");
}
public void methodChild() {
System.out.println("method in Child");
}
}
public class Main {
public static void main(String[] args) {
B[] b = new B[10];
A[] a = b;
a[0] = new A();
b[0].methodParent();
}
}
这段代码如果运行将会报错
Exception in thread "main" java.lang.ArrayStoreException: aliasingtest.A
at aliasingtest.Main.main(Main.java:26)
需要修改
B[] b = new B[10];
A[] a = b;
a[0] = new B();
b[0].methodParent();
因为B[] b = new B[10];
已经定义了数据类型为B,Java
是强类型语言
堆与栈
class A {
int x;
int y;
}
...
public void m1() {
int i = 0;
m2();
}
public void m2() {
A a = new A();
}
对应的堆栈存储图为
Java运行时数据区域
下图显示了整个JVM运行时数据区。
各个线程栈区数据不共享,堆区、方法区、运行时常量区数据共享。
栈数据包括
局部变量数据组、操作栈、常量池数据引用