String是我们经常用到的一个类型,其实有时候觉得写程序就是在反复的操作字符串,这是C的特点,在java中,jdk很好的封装了关于字符串的操作。今天主要讲的是三个类String 、StringBuffer 、 StringBuilder .这三个类基本上满足了我们在不同情景下使用字符串的需求。
先说,第一个String。
JDK的解释是 “Strings are constant; their values cannot be changed after they are created”也就是说String对象一旦被创建就是固定不变的了(你一定有问题,但请先等一等,耐心读下去),这样的一点好处就是可以多线程之间访问,因为只读不写。
一般情况下我们以下面两种方式创建一个String对象
两种方式是有区别的,这和java的内存管理有关,前面已经说过,string创建之后是不可变的,所以按照第一种方式创建的字符串会放在栈里,更确切的是常量池中,常量池就是用来保存在编译阶段确定好了大小的数据,一般我们定义的int等基本数据类型就保存在这里。
其具体的一个流程就是,编译器首先检查常量池,看看有没有一个“string”,如果没有则创建。如果有的话,则则直接把str1指向那个位置。
第二种创建字符串的方法是通过new关键字,还是java的内存分配,java会将new的对象放在堆中,这一部分对象是在运行时创建的对象。所以我们每一次new的时候,都会创建不同的对象,即便是堆中已经有了一个一模一样的。
写一个小例子
- String str1 = "string";
-
String str4 = "string";
-
String str2 = new String("string");
-
String str3 = new String("string");
-
-
- System.out.println(str1 == str4);
- System.out.println(str2 == str3);
- System.out.println(str3 == str1);
-
-
str3 = str3.intern();
- System.out.println(str3 == str1);
这个的运行结果是
true //解释:两个字符串的内容完全相同,因而指向常量池中的同一个区域
false //解释:每一次new都会创建一个新的对象
false // 解释: 注意==比较的是地址,不仅仅是内容
true //介绍一下intern方法,这个方法会返回一个字符串在常量池中的一个地址,如果常量池中有与str3内容相同的string则返回那个地址,如果没有,则在常量池中创建一个string后再返回。实际上,str3现在指向了str1的地址。
这就是让人纠结的string了,现在你可以说话了。。。很多人有这样的疑问就是既然string是不变的,那么为什么str1 + "some"是合法的,其实,每次对string进行修改,都会创建一个新的对象。
所以如果需要对一个字符串不断的修改的话,效率是非常的低的,因为堆的好处是可以动态的增加空间,劣势就是分配新的空间消耗是很大的,比如我们看下面的测试。
- long start = System.currentTimeMillis();
-
-
for(int i = 0; i < 50000; i++)
- {
-
str1+= " ";
- }
-
-
long end = System.currentTimeMillis();
-
System.out.println("the run time is "+(end -start)+" ms");
我的机器上运行结果是the run time is 3538 ms 如果你把循环的次数后面再增加几个0就会更慢。因为每一次循环都在创建心的对象,那么JDK如何解决这个问题?
下面就要说第二个类StringBuffer。
StringBuffer是一个线程安全的,就是多线程访问的可靠保证,最重要的是他是可变的,也就是说我们要操作一个经常变化的字符串,可以使用这个类,基本的方法就是append(与string的concat方法对应)和insert方法,至于怎么使用,就不多讲了,大家可以自己查看API。
- StringBuilder sb = new StringBuilder("string builder");
-
StringBuffer sf = new StringBuffer("string buffer");
-
-
long start = System.currentTimeMillis();
-
-
for(int i = 0; i < 50000; i++)
- {
-
-
sb.append(" ");
- }
-
-
long end = System.currentTimeMillis();
-
System.out.println("the run time is "+(end -start)+" ms");
测试一下,这次只需要8ms,这就是效率。
那么接下来,就要问StringBuilder是干什么的,其实这个才是我们尝使用的,这个就是在jdk 1.5版本后面添加的新的类,前面说StringBuffer是线程同步的,那么很多情况下,我们只是使用一个线程,那个同步势必带来一个效率的问题,StringBuilder就是StringBuffer的非线程同步的版本,二者的方法差不多,只是一个线程安全(适用于多线程)一个没有线程安全(适用于单线程)。
其实看了一下jdk源代码就会发现,StringBuffer就是在各个方法上加上了关键字syncronized
以上就是对三个字符串类的一个总结,总之不要在这上面纠结。。。。。。不想介绍太多的方法,总觉得那样会把一篇博客弄成API文档一样,而且还非常的繁琐。都是些体会,希望有所帮助。起码不要再纠结,尤其是面试。。。。
本文完整源代码:https://github.com/octobershiner/Java-Taste/tree/master/StringDemo
欢迎关注JavaTaste项目 https://github.com/octobershiner/Java-Taste
系列文章:http://www.cnblogs.com/octobershiner/archive/2012/03/17/2404154.html
分享到:
相关推荐
string的种种,纠结,希望这篇文章让大家不再纠结。。 string是我们经常用到的一个类型,其实有时候觉得写程序是在反复的操作字符串,这是C的特点,在java中,jdk很好的封装了关于字符串的操作。主要讲的是三个类...
同时,掌握Java的基本数据类型,注意它们与你可能熟悉的其他语言之间的差异,特别是String类,它在Java中有着特殊的地位。 接着,学习继承。这是面向对象的一个关键特性,它允许你创建新的类,基于已有的类进行扩展...
在Java中,`throw`关键字用于手动抛出一个异常,而`throws`关键字用于声明方法可能会抛出的异常类型。两者的主要区别如下: - **throw**:它是一个关键字,用于抛出一个具体的异常实例。例如: ```java throw new...
例如,在JDK1.5及以上版本中,可以使用`PolicyFile`类来实现这一点。 #### 2. 粘包问题 “粘包”是指在网络传输过程中,多个数据包被错误地合并成一个数据包的现象,这会导致接收方无法正确解析数据。 - **问题...
在Java中,可以定义一个接口来代表回调函数,并使用`Callback`类来传递给原生函数。 ```java import com.sun.jna.Callback; import com.sun.jna.Pointer; import com.sun.jna.WString; public interface ...
纠结了很久都没解决,今天终于弄好了,文件包中附带了修改好的jar包bsj-poi-ooxml-3.10-FINAL-20140208.jar。主要问题是出在:org.apache.poi.xwpf.usermodel.XWPFRun.addPicture()函数 解决的是 // Pesky ...
在Android中,JNI函数默认在创建它的线程中执行,即如果Java层调用了一个JNI方法,该方法会在Java的UI线程中运行。这可能导致阻塞UI,所以有时需要在JNI中创建独立的线程。在示例代码中,`naitveThread()`函数可能...
笔主利用这个七夕前后两天的寂寞时光,用JAVA磨了一个简单的图像相似度计算小程序,在刚才终于纠结完毕,输出了1.0版本,小小的满足了一下可怜的虚荣心.. UI设计图: 实际运行效果图: 关键算法: 1 /...
这个"jsoup.jar包"就是将jsoup库打包成的Java可执行文件,方便在Android项目中直接引用。 1. **HTML解析** - Jsoup解析HTML时,会将其转化为一个DOM树结构,使得我们可以像操作XML一样操作HTML。这种解析方式使得...
在Android应用开发中,Model-View-Presenter(MVP)是一种设计模式,它将业务逻辑、用户界面和数据模型分离开来,提高了代码的可测试性和可维护性。本篇文章将详细探讨如何在包含多个Fragment的Android应用中实现MVP...
在Struts2中,Action类中的方法负责处理来自客户端的请求。为了返回JSON数据,可以定义一个如下的Action方法: ```java public String getXxx() { return "aaa"; } ``` 当客户端调用此方法时,Struts2会自动将...
关于这个token随便填不要纠结,下面直接看JAVA代码 package com.base.action; import java.io.PrintWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java
Android 中的 Bitmap 是一种特殊的类,它不能被直接创建,而只能通过 BitmapFactory 来获取。BitmapFactory 提供了多种方法来从不同的图像来源中获取 Bitmap,下面是其中的一些: 1. 从资源文件中获取 Bitmap 可以...
在这个例子中,我们在JavaScript中可以通过`window.myObject.doSomething`来调用Java方法`doSomething`。为了安全起见,所有暴露给JavaScript的接口都需要加上`@JavascriptInterface`注解。 JavaScript与Android...
您可能听说过 ToStringHelper,这是 Google Guava 项目 (MoreObjects#toStringHelper) 中的一个很棒的工具。 这不是那个。 不过,它非常相似。 ReflectiveToStringHelper(或只是 RTSH – arr tush)使用 Java 的...
在Java Web开发中,`Filter`是一种功能强大的机制,它能够拦截客户端请求,并在请求到达目标资源(如Servlet)之前或之后进行处理。这为开发者提供了极大的灵活性来添加诸如编码处理、登录验证、权限检查等功能。 #...
它解决了中文环境下使用 DocBook 的诸多痛点,使得用户能够更专注于撰写文档本身而非纠结于繁琐的技术细节。 #### 二、基础知识 - **DocBook**: 一种用于创建技术文档的标准格式,基于 XML 语言,被广泛应用于编写...
`WebSettings`类提供了许多配置选项来优化WebView的性能和行为。例如: - `setUseWideViewPort(true)`:使WebView适应宽屏设备。 - `setLoadWithOverviewMode(true)`:在页面加载时尽可能保持缩放比例。 - `...
DBUtils的核心类`QueryRunner`提供了多种方法来执行SQL语句,包括查询、更新等。 1. **增删改查操作**: ```java public void add() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils.get...