String图解

以/**开始叫文档注释


 

当java中用双引号""创建这么一个字符串的时候,那java就会在堆里面创建一个String类型的这么一个字符串,然后这个字符串,它结构是这样的,这字符串里面主要有一个属性value,value是char[]数组类型,那这个数组怎么回事呢?

这么做的。数组肯定是个对象,是个引用,它引用了什么?它引用了一个数组类型的这么一个对象(char[]),

这个对象数组类型的,然后这个数组中放了字符A B C 三字符

字符串底层封装了一个什么?字符数组

之后把它的字符串引用交给s1,那我们就会在栈里面定义一个变量叫s1,而s1的值引用了对象



那为什么s1这个变量放栈里?因为是main方法中声明的变量

记住:方法中声明的所有变量都是放在栈里的,而对象都在堆里

提问:是不是所有引用变量放栈里?错误,比如上图s1是个引用变量,在栈里,value是个引用变量,在堆里

value也是个引用类型变量,它引用了一个char[]数组

String s2=s1;//把s1的引用传给s2,s2是个新变量,也是在新方法中声明的,那s2的值是什么?是s1的值交给s2

这样s1和s2具有相同的对象的首地址,那这样s2的值它也引用同一个对象

s1=s1+"DEF";

java的加法其实在底层,它是做一个字符串的合并,就是这个结构又出现了一遍,但是这个时候,它不叫ABC里面放的是DEF,

也就是先算"DEF",再去画加法


这是第二个字符串,而这个连接是把他连接在一起,而数组长度能改变吗?不能


那现在我希望生成个新字符串,里面那个数组啊是前面两个数组和,所以java在底层对数组进行扩容了,就是java

又创建一个字符串,而这个字符串引用一个新数组,这个数组就是一个扩容的数组,扩容以后,新数组的长度是两个数组长度的和,

然后把这个复制以后的结果,这个对象的引用交给value


 

扩容以后把ABCDEF复制过来,然后把复制以后的这个结果,这个对象的引用交给value



 

字面量:就是直接写的,比如"ABC",123,直接写死的,

常量:解释双等号的问题==


在这里a的值是5,b的值是5,那a跟b相等,其实就是底下的一个二进制相等

比较结果显然是true

String字面量的缓存重用现象

String s1 = "ABC";

String s2 =s1;

System.out.println(s1==s2);

结果为true://这个true什么意思?

是s1的地址值和s2的地址值一样

也说明是s1和s2引用同一个对象

那现在我要定义一个字符串,s3,让他也等于字面量"ABC"

这个时候java就会怎么做呢?是这样的,因为第一次创建"ABC"的时候,java会把ABC的引用放到常量池里边

缓存起来了

再用的时候,Java进到池里去找,用旧的

s1==s3        


java凡是看到这种字面量"ABC",就会在堆里创建一个数据结构---常量池(存的引用)

这个引用它引用了字符串对象





s3的引用从常量池里面拿出来


字符串连接结果不参与优化


不是字面量的不缓存,s6就不是字面量,它是加起来的结果



/**
* String 字符量的缓存重用现象 
* 提高字符串的性能!!!节省内存耗用

* 1. 直接写出的量称为字面量:"ABC" 5 3.14
* "ABC" 字符串字面量
* 2. Java 为了性能,优化字符串"字面量"对象
*     将String对象引用缓存到常量池.
* 3. 使用相同字符串"字面量"时候, 替换为
*    相同的字符串对象引用
* 4. 字符串常量 和 字面量连接的结果 也作为
   字面量优化

比如    public static final String S = "ABC";

//字符串常量和字符串字面量一同优化
System.out.println(S==s1);//true

//"字面量"的连接结果
String s7 = "A"+"B"+'C';//        'C'是字符类型 ,是字符字面量,前面AB是字符串字面量              //"ABC"

那这些字面量连接完了,它也当字符串字面量

为什么?

因为java的编译器,它在编译期间能算的先算了,编译的时候是ABC,运行期间还是ABC,所以编译器事先知道这个运算结果永远就是ABC了,所以编译器在编译阶段把这个字面量连接完了   //"ABC"

但这个是字面量的连接结果

是不是变量?不是,它是字面量,跟刚才的s6不一样,s6是两个变量的连接结果,编译器不管

所以System.out.println(s7==s1);//true

* 5. 其他通过new运算,或者字符串变量连接的
*    结果是新字符串对象,不参与常量池优化
*/

单引号引的数据 是char类型的
双引号引的数据 是String类型的

char定义时用单引号,只能有一个字母,数字。char c='c';
而String用双引号,可以是一个,也可能是多个字母,汉字等。就是所谓的字符串。String s="adsaf";
char只是一个基本类型,而String 可以是一个类,可以直接引用。
比如char c='c';不能直接对c调用方法。
String s="abc";  这时可以调用s.charAt(0);等方法,因为String是类,这是就是对象的调用了


//经典面试题目:
String s8 = new String("ABCD");
//如上程序运行期间创建了几个字符串对象:
//A.1个, B.2个  C.3个  D.4个

参数先算--"ABCD"

再进行new运算--new就会new一个字符串对象



上图还是稍微有点问题,更正一下,真正的java字符串在底层为了提高效率,为了节省内存


实际上,java连数组都进行重用

字符串里面存的是字符,而每个字符都是Unicode编码

package se1.day01;


public class LengthDemo03 {


public static void main(String[] args) {
/**
* String 类型提供了length()方法
* 返回字符串中字符的个数

 * 面试点: 数组长度是属性(.length), 字符串长度是方法(通过String自带的length()方法取字符串长度

* length: 长度
*/
String s1 = "Hello 世界!";
//                0123456 7 8
int l = s1.length();
System.out.println(l);//9(0到8)
char c = s1.charAt(6);//按照位置获取字符
System.out.println(c);//世
/**
* getBytes()对字符串进行编码, 并且返回
* 编码以后的结果, 不同编码返回字节数量不同!
* getByte方法返回在字节长度不是内存中
* 实际占用的字节长度! 以后在编码课程专门讲
*/
byte[] bytes = s1.getBytes();//这个getbytes[]不是去取得字符串中我们理解的那个byte

比如一个字符,是一个char,是两个byte----不是这个byte

getBytes()对字符串进行编码, 并且返回编码以后的结果, 不同编码返回字节数量不同!

返回值不是实际内存中存储的字节数,而是内存存储的字符串经过指定的编码,那编码以后那个结果的数量

getByte方法返回在字节长度不是内存中

int l =s1.charAt(6);//按照位置获取字符          //世

char 变量=字符串变量.charAt(数字)


System.out.println(bytes.length);
}
}

----------------------------------------------------------------------------------

检测一个人的姓名中包不包含王字

/**
* indexOf方法
* 在一个字符串中检索指定字符串出现的位置
* 如果找到了字符串,返回字符串的位置,否则
* 返回 -1

* 如果一个人的姓名第一个字符是"王"的话,则
* 这个人姓王------从前往后比

*/
Scanner in = new Scanner(System.in);
System.out.print("输入姓名:");
//            "宋哲"
String name = in.nextLine(); // "王宝强";
//             0 1 2
int n = name.indexOf("欧阳");//"欧阳"
System.out.println(n);
if(n==0){
System.out.println("这位仁兄姓欧阳"); 
}








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值