String a=“aa”;
String不是一个基本的数据类型,而是引用类型,对于以上简单的一句话再Java编译器看来再编译阶段是可以确定下来的,那么就把“aa”对象存放在当前class文件的常量池区域(注意不是堆,具体来说是Perm区),常量池同样也是可以再运行时扩充的,例如“XXX”.intern()的调用,就是运行时向class的常量池中注入数据,不断注入可以导致java.lang.OutofMemory:PermGen space异常。流程大概是先拿这个字符串与常量池中得每个字符串进行equels比较,如果存在一致的则返回常量池的引用,如果都不存在再注入常量值并返回当前地址,可见String.intern()的效率并不高。
private static void test1(){ String a = “a” + “b” +1; Stirng b = “ab1”; System.out.println(a==b); }
显然返回结果为True
关于”==“:对于基础数据类型来说==是比较基本数据类型的值如(byte,short,int,float,char,double,long,boolean),而对于引用类型,比较的是两个引用对象的逻辑地址
关于equels和hashcode():Object类的equels方法默认就是比较的两个对象引用的逻辑地址(return (this == obj);),equels的设计就是要子类来自己实现比较两个相同的子类(对于不同的子类来比较是没有任何意义的,所以看到很多equels的实现中都是先判断两个对象是不是属于一个类)对象是否是相等的,这里不是引用的地址是否相等。java默认的hashcode方法提供了对象的hash值,他是一个native方法(native的方法调用成本还是很高的),他的返回值与System.identifyHashCode(Object)方法的返回值一致,通常情况下是对象头部的一部分二进制组成的数字,hashcode方法可以说是标识对象,用以再hash算法中将对象散列开。String类重写了HashCode方法,需要遍历char[]的所有的char来生成对应的String类的hashcode,对象其实equels方法和hashcode本身并没有什么关系,只是一些类的使用上导致了大家认为重写equels()方法就一定要重写hashcode()方法。如HashMap(还有HashSet,但是HashSet是使用HashMap来实现的),HashMap中put一个元素的过程是先调用key的hashcode方法,根据这个方法的返回值和HashMap中Entity数组的长度计算出Entity的index,如果这个index上已经有了元素的话在调用key的equels方法进行比较,如果存在想通的就替换,如果不存在就插入链表。
关于编译时优化:对于编译器来说编译时优化秉承的原则就是能确定的就优化(例如final),确定不了的就不处理,对于final类型的变量进行优化,对于方法调用不进行优化,注意String a=“a” + “b”是在编译时优化为a=“ab",而String a=“a” String b=a+”b”在编译时优化为Stringbuffer的拼接
Atas ialah kandungan terperinci 解读java中的String类. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!