第5章 字符串答辩.docx

上传人:b****1 文档编号:23088582 上传时间:2023-04-30 格式:DOCX 页数:29 大小:1.63MB
下载 相关 举报
第5章 字符串答辩.docx_第1页
第1页 / 共29页
第5章 字符串答辩.docx_第2页
第2页 / 共29页
第5章 字符串答辩.docx_第3页
第3页 / 共29页
第5章 字符串答辩.docx_第4页
第4页 / 共29页
第5章 字符串答辩.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

第5章 字符串答辩.docx

《第5章 字符串答辩.docx》由会员分享,可在线阅读,更多相关《第5章 字符串答辩.docx(29页珍藏版)》请在冰豆网上搜索。

第5章 字符串答辩.docx

第5章字符串答辩

一.String类

1.了解类和对象

String类

Strings="aaa";

"aaa"、"HelloWorld"String的对象

一个String类可以创建多个对象

s不是对象是对象的引用变量

对象:

模拟现实世界中的事物…

具体的概念,它是类的实例

现实世界编程世界

具体的一个学生赵英龙学生对象(name是赵英龙)

具体的一个笔记本老师用的这台笔记本笔记本对象

aaa、你好String对象

类:

意义上相近的对象的集合

学生类笔记本类

抽象的概念,概括的概念一个统称看不见摸不着的

2.如何使用String(4种方式)

1.直接赋值

Strings="aaa";

2.new对象

Strings=newString("aaa");

System.out.println(s);

3.newString(char[]charArr)

char[]charArr={'h','e','l','l','o','','j','a','v','a'};

//Strings=newString(charArr);

//System.out.println(s);

4.newString

Strings=newString(charArr,6,4);

System.out.println(s);

最常用的是前两种

3.String类的对象是字符串常量

String类创建的对象是不可变的字符串常量

一旦被创建内存中的值永远不变,改变的只是引用(对象的引用变量)

//代码1

Strings1=newString("aaa");

System.out.println("s1="+s1);

s1="bbb";

System.out.println("s1="+s1);

输出结果

s1=aaa

s1=bbb

分析

不是说String不可变吗?

为什么却改变了?

我们说的不可变是String对象,事实上这段代码s1指向了一个新对象,输出结果当然变了

//代码2

Strings1="aaa";

s1.concat("bbb");

System.out.println(s1);

结果

aaa

如果把s1.concat("bbb");改成s1=s1.concat("bbb");呢?

结果aaabbb

给学生画内存图

结论:

String类的对象一旦被创建内存中的值永远不变,改变的只是引用)

4.补充垃圾回收器

作用:

帮助程序员回收那些无用内存,让程序员从内存申请和释放中解脱出来

程序员不用写freedelete了

无用内存:

没有引用引用的对象无用内存会在某个时间内,比如说内存不够用

或CPU空闲的时候,垃圾回收器会释放这些无用内存.

二.简述一下final(面试题)

String类的对象一旦产生在内存中永远不变,改变的只是引用,如果想让引用也不能随便改变呢?

使用final

final修饰变量的时候

1.修饰基本类型

finaldoublePI=3.14;//最终变量表示常量//只能被赋值一次

PI=20;//编译错误不能为最终变量赋值

2.修饰引用类型

finalStrings="aaa";//最终引用只能引用一个对象不能再引用其他的了

s="bbb";//不能再赋值了编译报错

思考(这是对学生的更高要求)

怎样设计类才能产生不可变对象?

表示其状态的域成员都是final的,只可被初始化一次

补充:

String的实质---其实底层是字符数组

1.查看源代码

C:

\ProgramFiles\Java\jdk1.8.0_25\src.zip

publicfinalclassString

implementsjava.io.Serializable,Comparable,CharSequence{

privatefinalcharvalue[];//底层是字符数组

}

2.反编译

编译

.java----------------->.class

反编译

.class---------------->.java

cavaj反编译工具

String.class在C:

\ProgramFiles\Java\jdk1.8.0_25\jre\lib\rt.jar中

三.学习如何打断点调试代码

四.字符串连接

1.使用“+”号进行字符串连接

例如

Strings1="Hello";

Strings2=s1+"World!

";

System.out.println(s2);

输出结果

HelloWorld!

“abc”+2+2和2+2+”abc”结果是什么?

“abc22”

2.使用publicStringconcat(Stringstr)方法连接

五.字符串常量池

Strings1="aaa";

Strings2="aaa";

Strings3="aaa";

Strings4=s3+"aaa"+"aaa";

同一份字面值aaa,在堆里产生了5个重复的对象,这样比较浪费内存!

!

!

!

!

如果解决?

?

?

?

?

字符串常量池

java设计人员为了高效的使用内存,有了字符串常量池的概念.相同的字面值对象只在字符串常量池中创建一次就可以了,

当再出现相同的字面值对象时,不会创建新的对象,只是引用常量池中已经创建好的对象即可.

无则创建,有则返回

JVM虚拟机运行时,人为划分的内存分类

栈:

方法调用的入栈、方法执行完毕出栈,方法中的局部变量都在每个方法对应的栈帧中分配.

堆:

程序运行时动态分配的内存,一new创建的对象就在堆里。

方法区(静态区):

常量池在方法区里面

创建了几个对象(面试题==和equals的区别)

1.直接赋值

只会创建一个对象,在常量池中,无则创建,有则返回

Strings1="aaa";//创建了一个对象在常量池中

Strings2="aaa";//没有创建对象

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

System.out.println(s1.equals(s2));//true

2.new

new创建了两个对象:

1.常量池中(无则创建、有则返回)2.堆里(只要一new就一定会在堆里出现一个新的)

Strings1=newString("aaa");//创建了两个对象常量池中是字面值对象堆里是指向常量池中的地址

Strings2=newString("aaa");创建了一个对象堆里那个

System.out.println(s1==s2);//false不是引用同一个对象

System.out.println(s1.equals(s2));//true

System.out.println(s1.intern()==s2.intern());//true

==和equals区别

==实质比较的是二进制位

1.==两边是基本类型的情况

inta=10;

intb=20;

System.out.println(a==b);//false

2.==两边是引用类型的情况

比较的是地址,其实比较的是引用的是否是同一个对象,如果引用的是同一个对象就是true,不是同一个对象就是false

equals

现在的equals指的String类的equals,比较的是字面值,如果字面值相同,返回true,不相同返回false

intern()方法

s1.intern()的意思s1指向的堆里的对象对应的真正的常量池中字面值的地址1

String类的常用方法

常用方法1

•publiccharcharAt(intindex)

–返回字符串中第index个字符

•publicintlength()

–返回字符串的长度

•publicintindexOf(Stringstr)

–返回字符串中出现str的第一个位置

•publicintindexOf(Stringstr,intfromIndex)

–返回字符串中从fromIndex开始出现str的第一个位置

•publicbooleanequalsIgnoreCase(Stringanother)

–比较字符串与another是否一样(忽略大小写)

•publicStringreplace(charoldChar,charnewChar)

–在字符串中用newChar字符替换oldChar字符

常用方法2

•publicbooleanstartsWith(Stringprefix)

–判断字符串是否以prefix字符串开头

•publicbooleanendsWith(Stringsuffix)

–判断字符串是否以suffix字符串结尾

•publicStringtoUpperCase()

–返回一个字符串为该字符串的大写形式

•publicStringtoLowerCase()

–返回一个字符串为该字符串的小写形式

•publicStringsubstring(intbeginIndex)

–返回该字符串从beginIndex开始到结尾的子字符串

•publicStringsubstring(intbeginIndex,intendIndex)

–返回该字符串从beginIndex开始到endIndex结尾的子字符串

•publicStringtrim()

–返回将该字符串去掉开头和结尾空格后的字符串

substring(start,end)前面包含后面不包含

演示代码:

Strings="hello!

";

s=s.substring(1,4);

System.out.println(s);//ell

演示代码

publicclassTestStringMethod{

publicstaticvoidmain(String[]args){

Strings1="sunjava";

Strings2="SunJava";

System.out.println(s1.charAt

(1));//u

System.out.println(s1.length());//8

System.out.println(s1.indexOf("java"));//4

System.out.println(s1.indexOf("Java"));//-1

System.out.println(s1.equals(s2));//false

System.out.println(s1.equalsIgnoreCase(s2));//true

Strings="我是蓝桥软件学院的学生,我在学java!

";

Stringstr=s.replace('我','你');

System.out.println(str);

}

}

字符串分割方法

•publicString[]split(Stringregex)可以将一个字符串按照指定的分隔符分隔,返回分隔后的字符串数组

Stringstr="足球,篮球,羽毛球";

String[]strArr=str.split(",");

for(Strings:

strArr){

System.out.println("我爱"+s);

常用方法3

•静态重载方法

–publicstaticStringvalueOf(…)可以将基本类型数据转换为字符串,例如

•publicstaticStringvalueOf(inti)

•publicstaticStringvalueOf(doubled)

基本类型、包装类型、字符串三者转换

1.基本类型---->字符串

String的静态方法valueOf可以把基本类型转换成字符串

演示代码:

StringstrA=String.valueOf

(1);//把基本类型-->字符串类型

System.out.println(strA.equals("1"));//true

2.字符串------->基本类型

Strings="12345";

intintS=Integer.parseInt(s);

System.out.println(intS);

公式

基本类型=包装类名.parseXXX(字符串)

StringsDouble="3.14";

doubled=Double.parseDouble(sDouble);

System.out.println(d);

3.基本类型-------->包装类型

纯面向对象

基本类型不是类

int-------->Integer(包装类型)

第一种转换方式

IntegeraInteger=newInteger(a);

第二种方式

Integera=20;//自动装箱auto-boxer

System.out.println(a);

装箱:

基本类型--->包装类型

4.包装类型----->基本类型

(1)自动拆箱

Integera=20

intb=a;//自动拆箱auto-unboxer

System.out.println(b);

拆箱:

包装类型--->基本类型

(2)xxxValue

IntegerintegerA=20;

intb=integerA.intValue();

System.out.println(b);

5.包装类型-------->字符串

IntegerintegerA=newInteger(111);

StringstrA=integerA.toString();

System.out.println(strA);

//6.字符串----->包装类型

//如果类型不匹配会出现异常java.lang.NumberFormatException

Strings="aaa";

IntegerintegerA=newInteger(s);

System.out.println(integerA);

面试题:

jdk5.0新增的功能

1.增强的for循环

2.自动装箱和自动拆箱

boolean

char

intlongfloatdouble

byteshort

基本类型包装类型

charCharacter

intInteger

其他的都是首字母大写

StringBuffer和StringBuilder(字符串变量)

使用

•实际中常用的创建方式有两种

–StringBuffersb=newStringBuffer(“”);

•sb.length()长度为0

•但底层是创建一个长度为16的字符数组

–StringBuffersb2=newStringBuffer(“Hello”);

•sb.length()长度为5

•底层是创建一个str长度+16的字符数组

•举例说明

StringBuffersb=newStringBuffer("aaa");

System.out.println(“sb=“+sb);

sb.append("bbb");

System.out.println(“sb=“+sb);

输出结果

sb=aaa

sb=aaabbb

 

面试题:

String、StringBuilder和StringBuffer的区别?

?

?

?

String字符串常量,String类创建的对象是不可变的(值一旦创建,内存中的值永远不变),改变的只是引用

StringBuilder和StringBuffer字符串变量

StringBuffer是线程安全版本的StringBuilder,StringBuffer支持多线程

StringBuilder是非线程安全的,不支持多线程,只能在单线程下工作,而且单线程效率高,推荐使用StringBuilder

StringBuilder底层代码分析

当16个满了以后扩充成34

规律16*2+2

16--->34

34--->70

演示代码

packagecom.chapter5;

publicclassTestStringBuilder{

publicstaticvoidmain(String[]args){

System.out.println("演示StringBuilder");

//1.第一种创建方式

StringBuildersb=newStringBuilder();//底层创建了一个长度为16的字符数组

sb.append("aaaaa");

sb.append("aaaaa");

sb.append("aaaaa");

sb.append("a");

sb.append("aaaaa");

sb.append("aaaaa");

sb.append("aaaaa");

sb.append("a");

sb.append("aa");

sb.append("aaaaa");

System.out.println(sb.length());//0

System.out.println(sb);

}

}

关键代码

append实质调用了AbstractStringBuilder类的append方法

a

publicAbstractStringBuilderappend(Strings)

{

if(s==null)

{

s="null";

}

inti=s.length();//1

ensureCapacityInternal(count+i);//1

s.getChars(0,i,value,count);

count+=i;

returnthis;

}

17

privatevoidensureCapacityInternal(inti)

{

1-16

if(i-value.length>0)

{

expandCapacity(i);

}

}

17

voidexpandCapacity(inti)

{

16*2+2=34

intj=value.length*2+2;

17<0

if(j-i<0)

{

j=i;

}

if(j<0)

{

if(i<0)

{

thrownewOutOfMemoryError();

}

j=0x7fffffff;

}

value=Arrays.copyOf(value,j);//创建了一个长度为j=34的数组并把以前的数组value的元素拷贝到新数组中,返回新数组

//然后让value引用新数组

}

 

什么使用想到用字符串变量StringBuilder或StringBuffer呢?

如果我们写的程序,字符串经常发生改变,推荐使用这两者

 

Strings="I";

Strings1=s+"like";

Strings2=s1+"java";

 

会额外产生辅助对象likejava,这些辅助对象创建、回收都是需要时间的,浪费时间,效率低,而且辅助对象浪费内存.

 

其实,我要的结果Ilikejava,所以推荐使用StringBuilder

课外学习

编译器对String拼接的优化

•举例说明

–Strings1="I";

Strings2=s1+"like";

Strings3=s2+"java";

•JDK5.0以前版本执行过程

–Strings1=“I”;//常量池中创建“I”的对象

–常量池中创建like对象

–s1+”like”执行后创建“Ilike”对象,并用s2引用它

–常量池中创建”java”对象

–s2+“java”执行后创建”Ilikejava”对象,并用s3引用它

•结论

–创建了5个对象“I”、“like”、“Ilike”、“java”、“Ilikejava”

–其中被引用的对象有“I”、“Ilike”、“Ilikejava”,而”like”、“java”没有被引用

–创建了多余的辅助对象“like”、“java”耗费了内存和时间

–同时垃圾回收期要对这些无引用变量引用的对象进行回收,同时耗费了时间,损害了性能

•怎么样解决这个问题?

使用StringBuilder优化

JDK5.0以后会把String对象的+操作转换成StringBuilder的append操作

JDK5.0以后版本执行过程

–Strings1=“I”;//常量池中创建“I”的对象

–s1+“like”;执行后使用s1引用的字符串字面值创建StringBuilder对象“I”,同时把+操作转化成append操作,直接生成“Ilike”,然后把该StringBuilder对象转换成String对象“Ilike”,并用s2引用它

–之后类似

结论

–创建了5个对象,“I”常量池对象、“I”StringBuilder对象、String对象”Ilike”、StringBuilder对象“Ilike”、String对象“Ilikejava”

–其中被引用的对象有“I”、“Ilike”、“Ilikejava”

–创建了两个StringBuilder辅助对象,在单行语句+操作比较多的情况下可以显著减少生成的辅助对象

–同时也省去了垃圾回收器对这些额外生成的无引用变量引用的辅助对象进行回收的时间,提高了性能

–主要是对同一行频繁+操作的内存优化

–优化后代码如下

–Strings1="I";

Strings2=(newStringBuilder(String.valueOf(s1))).append("lik

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > IT计算机 > 互联网

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1