Java中String的那点事!

来源:互联网 发布:淘宝利返利是真的吗 编辑:程序博客网 时间:2024/05/18 16:54

今天,记录下Java中String的一点相关的知识,补足一下自己的知识储备。
很多初学者可能会跟我一样天真的认为String会是8大基本类型中的一种!这是完全错误的(手动滑稽自己)。为大家普及一下,8大基本数据类型:int、short、boolean、long、byte、char、float、double。就是这些,现在千万要记住了!
再说String,为大家附上一张Java源码中的String代码图。具体的还需要各位自己去查阅。
这里写图片描述
我今天所说的知识自己学到的一小部分,大手勿喷。从源码当中可以看见,String被final所修饰,很显然,String是一个不能被继承的类,同时也是一个被定义之后就不能修改的类。(是不是开始怀疑人生,自己以前修改的莫非是…)String对象代表的是一组不可以改变的Unicode字符序列,对它的任何一次修改,实际上是产生了一个新的对象,只不过你的引用是指向新的对象,你看不出来而已。然后Java的垃圾回收机制,将没有被指向的对象进行回收(个人认为).
String s = “123”
String s1 = “123”
s和s1指向的都是内存中“123”所在的地址,他们本质上是相同的,只是引用的名字不一样。就类似我给你取了一个外号,它跟你的名字一样,都是代表你。但是如果使用的是new方法进行动态的创建的话,那么就必须在对内存中开辟另外一块区域,用来存新的对象。怎么说呢,这就好比分身术,又出来一个跟你一模一样的你(我也不知道比较是否恰当,敬请指正),但是现在一样的名字,就不再是你了,因为你的分身又是一个新的对象了。
接下来,我们来说一说String的比较方法。记得我在Java的equals和==关系中说过,在没有重写equals方法的时候,==
和equals的效果是一样的。所以,你动态分配和静态分配的时候,两者的地址发生了根本性的变化,不能再以老眼光来看了。下面举个例子:
String s = “123”
String s1= “123”
String s2 = new String(“123”)
s和s1进行比较的时候,两个引用指向的是同一个地址,而且字面量也是完全相同的,所以将会返回true;但是s或者s1跟s2进行比较的时候,两个都会返回false。结果为什么会这样,想必大家都很清楚了。我今天说的是下面这几种情况:
package test;

public class TestString {public static void main(String[] args) {    String m ="a";     String a = "b";    String me = "a"+"b";    String  all = "ab";    String mess = m + a ;    System.out.println(me ==all);    System.out.println(me == mess);    System.out.println(all == mess);}

}
大家可以猜测一下,这个的结果是什么。
在进行这几个值的比较的时候,只有me == all 返回的是true,然后mess 与me
、all进行比较的时候都是返回的false。这是因为,编译器在编译期间自动就将常量进行了拼接,将其组成一个字符串并且将这个常量放入常量池当中。但是存在引用的时候,编译器是不能够进行+操作的。因为+操作是在运行期间进行的,所以引用进行+操作的时候会重新为拼接后的字符串创建一个新的对象,然后再进行比较。(所谓的编译,就是你在写代码的时候键入的源代码编译器会主动帮你检测,生成一类文件,然后交由JVM(自己的理解))。但是如果这个引用是使用final修饰的话(但是值一定要是已知的,比如是赋值的常量,不能使用类似方法去获取),那么就类似常量进行拼接。
同时,在进行字符串定义的时候,系统会主动检测常量池中是否有类似的对象,如果有,引用则直接指向这个栈中的地址;如果没有,那么将新建一个对象放入其中。如果使用的是new,那么将指向堆中的这个对象。(另外基本数据类型我只测试了int,其他的还希望你们自己去测试,以便验证)。或许还有很多的初学者没有弄明白编译和运行到底怎么区分,下面我说一下自己的拙见:我认为编译其实在我们敲代码的过程中就在进行,正如我们在编译器中键入代码一样,编译器自动就会为我们检测,这个时候我认为就是在编译。然后运行,就是我们使用运行命令运行的时候,那个时候将会做更加深度的计算以及解读。
好了,今天就说到这里,希望自己加油!也希望你们加油!