前言:
做过java开发的程序员肯定都知道java中String的特殊性。最近学习和整理了一下关于String的知识点,希望对于java的初学者能有所帮助,彻底征服String这个磨人的小妖精。 我尽量讲的明白一些,如果哪里有讲的不清楚的,或者读者感觉表达模糊的,希望读者可以和我沟通,我们共同进步,因为我现在也是处在一个学习的阶段。
一. String是什么
- String是什么数据类型:
我们都知道java中有两大数据类型(基本数据类型和引用数据类型),而据我所知,除了八大基本数据类型(byte,short,int,long,float,double,char ,boolean)之外的都是引用数据类型,那么到这里你应该知道String属于什么类型吧?没错。String就是一个引用数据类型,但是如果说这个小妖精只是一个普通的引用类型,那今天这篇说明也是妥妥的没有必要了呢!怪就怪在,她虽是个引用数据类型,但是他却可以用处理基本数据类型的方式来处理,这是因为java的底层对她进行了封装,让程序员可以像使用基本数据类型一样的去使用她。并且这里涉及了一些java的内存分配机制在里面。我会尽量用自己所掌握的知识讲的明白些。
二. String 如何创建对象
按理来说,String是个引用类型,那么正常的流程,创建对象应该是new对象。但是,String却可以像基本数据类型一样可以直接采用赋值运算符(=)创建对象,下面介绍一个两个方法创建对象的不同点以及这两种方式创建对象时分别存在内存的什么位置。
第一种方法:通过 ”=“创建对象
- 学习这个之前,我们有必要了解一点,java的内存分配机制,java的内存机制是很复杂的,这里浅谈一点,只是为了有助于理解String创建对象时的内存分配过程。在java中内存被分为堆和栈(暂时先这么理解),一个应用程序中只有一个堆,但一个线程就有一个栈,也就是说一个应用程序可能会有多个栈,所以堆的内存要比栈的内存大一些。而堆中有个字符串常量池,这个字符串常量池也是内存的一部分,是用来存储一些常量的,当我们采用赋值运算符创建String对象时,创建的对象就存在字符串常量池中。
- 例如:下面代码
String str = "abc";
//通过这种方式创建对象时,首先在栈中创建一个Str的变量,
//然后检查字符串常量池中有没有abc这个常量对象,如果有,直接使得str指向该常量;
//如果没有,则创建常量对象,使str指向创建的该对象。
第二种方法: 通过new创建对象
String str=new String("abc");
//通过这种方式创建对象时,首先在栈中建一个str变量;
//然后检查字符串常量池中是否有abc这个常量对象,如果有,直接创建一个该常量对象的拷贝对象放进堆中;
//如果没有,则先在常量池中创建一个abc的常量对象,然后在在堆中创建一个该常量对象的拷贝对象;
三. 当String作为参数传递时
1、首先我们应该知道什么叫参数传递,当定义一个方法的时候,可以给这个方法设置参数(这个参数 叫做形参),目的就是在调用该方法的时候,可以根据调用者的需求传递过来相应的参数作为操作数据,(这个传递过来的参数叫做实参)从而做一些逻辑处理;
2、 然后我们要知道基本数据类型作为参数传递时和引用数据类型作为参数传递时的不同;(接下来就会扯一点)
3、最后,我们要略懂java的内存分配机制。基本数据类型的变量值和变量名都是一起存在栈中的,而引用数据类型,栈中存的是该引用类型的对象的地址,而堆中才真正存储该对象。(关于这个java内存机制,可以在网上找其他博客,这里就不在累赘,毕竟这个java的内存机制不是一两句话就可以说清楚的)。
4、就是我们的重点,我们要知道String做参数时传递的是值还是对象
- 基本数据类型作为参数传递时
- 当参数传递的时候,是基本数据类型,那么参数传递的就是值。也就是说接收该参数的业务逻辑方法不会改变传递之前的那个变量的值,而是重新建一个变量,改变自己建的这个变量的值。
- 引用数据类型传作为参数传递时
- 当传递的参数的数据类型是引用类型的时候,传递的是指针地址。 也就是说当传递引用类型作为参数的时候,传递的是,=存在栈中指向某个一个对象的地址,因此,当你在执行接收该参数的方法的时候,会修改这个对象里的属性
那么当传递的参数的数据类型是Stirng的时候会是什么情况呢?
是传值还是传地址呢?
答案就是,不管采用那种方式创建对象,当String作为参数传递的时候,传递的都是值。在这里,与String同通过那种方式创建对象是没有关系的,两种不同的方式创建对象,只是在内存中存储的位置不一样而已
四 . String中的equals()和 ==
我们都知道。java中,object类是所有类的直接父类或间接父类,而equals()是属于object 类的方法。
1.所以必须注意的是equals()方法只能用来比较引用数据类型的引用地址,基本数据类型是不能用的。
2. 而 == 在基本数据类型中比较的是值的是否相等,在引用数据类型中比较的是引用地址是否相等。
在object中,equals()方法原本的含义是比较两个对象的引用地址,这个我们只要查看源码就可以知道。但是String重写了该方法
so:
String中
1.在String中equalse()方法用来比较两个String对象的内容是不是一样的;
2.== 依然比较的是两个String对象的引用地址是否一样。