理解Java最重要的8张图

一图胜千言,下面图解均来自Program Creek 网站的Java教程

字符串的不变性

  1. 定义字符串
String s = "abcd";

s持有字符串abcd的引用

2. 用一个字符串变量赋值另一个字符串变量

String s2 = s;

s2和s持有同一个对象的引用
理解Java最重要的8张图_第1张图片
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相等,她们两个对象不一定相等
    理解Java最重要的8张图_第2张图片
    ##一个常见的错误
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中的异常分为可检测异常和不可预知异常,她们的关系在下表中
红色的为受检查异常,任何受检测异常可以在方法体或者方法定义中抛出。必须在编译期完成。绿色的是不可测异常
理解Java最重要的8张图_第3张图片

Collection和Collections

  1. 这是两个完全不同的东西。Collection是Collection接口继承关系中的根接口,而Collections是一个包含很多操作集合元素静态方法的类。
    理解Java最重要的8张图_第4张图片
  2. Collection的继承关系
  3. Map的继承关系
    理解Java最重要的8张图_第5张图片

Java同步机制

别名

别名意味着可以为同一块内存区域给予不同的名称,这些名称可以是不同的类型。
理解Java最重要的8张图_第6张图片

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最重要的8张图_第7张图片

Java运行时数据区域

下图显示了整个JVM运行时数据区。

各个线程栈区数据不共享,堆区、方法区、运行时常量区数据共享。
理解Java最重要的8张图_第8张图片
栈数据包括
局部变量数据组、操作栈、常量池数据引用
理解Java最重要的8张图_第9张图片

你可能感兴趣的:(java)