String对象的几个理解

一、关于String对象
关于String对象,bbs上争论不休。
现在倾向的解释是:String s = “abc”;这个语句中s是一个引用,它指向对象”abc”。这样一来,下面的语句:
String s1 = “abc”;
String s2 = “abc”;只产生了一个对象,即:”abc”。
而String s = new String(“abc”);这个语句中s是一个对象。下面的语句:
String s1 = new String(“abc”);
String s2 = new String(“abc”);就产生了两个对象,它们是s1和s2。
有了上面的解释,我们就不难理解,为什么我们优先在代码中使用前一种表达方式,因为前一种方式是引用,不论你在代码中要使用多少个相同的引用,只产生一个对象。而后一种方式则即使多个对象的内容一样,它们也是不同的对象,有各自的内存开销;这就大大的增加了我们内存的开销。
同样,下面的代码以及它们的运行结果也就能解释了。
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
代码:System.out.println(s1==s2);
运行结果:true
代码:System.out.println(s1=="abc");
运行结果:true
代码:System.out.println(s1.equals(s2));
运行结果:true
代码:System.out.println(s1==s3);
运行结果:false
代码:System.out.println(s3.equals("abc"));
运行结果:true

二、String与StringBuffer的区别
既然语句:String s = “abc”;中的s是一个引用。那么,在下面的语句:
String s = “abc”;
s = s+”d”;中,就应该有三个对象:”abc”、”d”和”abcd”。引用s先是指向对象”abc”,后指向对象”abacd”。
这样,我们就能看出String和StringBuffer的区别来。对于下面的代码:
String s = “”;
for(int i=0;i<10;i++){
               s = s+i;
}
我们将产生10多个对象。而下面的代码:
StringBuffer sb = new StringBuffer();
for(int i=0;i<10;i++){
       sb.append(i);
}
只产生一个对象。
所以,在String对象需要进行相加的时候,使用StringBuffer要明显比使用String优越,特别是在循环相加的时候。
 
三、其他基本类型与String的转化
在实际的编码过程中,经常要将其他的基本类型转化为String类型,如上面的我们所常用到的例子:
String s = “”;
for(int i=0;i<10;i++){
        s = s+i;
}
中,s = s+i;语句中就需要将整型数据i转化为字符串,然后再与s相加。
其实,除了s = s+1;的这种转化方式,还有一种我们大家所不常用到的转化方式,如下:
s = s+Integer.toString(1);
经过大家对对上面两种转化方法所耗时间的测试,结果发现后面一种转化方式所耗的时间大大低于前面一种转化方式所耗的时间
所以大家在编码的过程中,不妨使用后面的一种转化方式。
 
四、Object类的toString()的重载
toString()方法是Object类的一个公有方法,Object类是Java所有类的父类。因此,任何其他的Java类都能重写该方法,为己所用。例如,所有的基本类型的包装类,如:Integer、Float、Double等等,都重写了toString()方法,功能是将该类型转化为String类型。
对toString()的重写一般用来提供一些关于这类的基本信息。如对于一个复数类,如下:
public class Complex{
        private double real;
        private double image;
        ……
}
它的toString()方法可以写为:
public String toString(){
        String ri = “”;
        if(this.image<0){
               ri = ri+”-”+Double.toString(Math.abs(this.image))+”i”;
        }
        else{
               ri = ri+”+”Double.toString(this.image)+”i”;
        }
        return Double.toString(this.real)+ri;
}
上面的这个toString()方法刚好表达了一个复数的数学表达式,这恰恰是我们在对复数做完运算以后希望得到的结果。
又如,对于一个员工类:Employee。我们最常用的、最希望看到的常常是他们的姓名,如下:
public class Employee{
        private String firstName;
        private String secodeName;
        ……
        public String toString(){
               return this.firstName+this.secodeName;
       }
……
}
所以,在一些类中,重写toString()方法是很有用的,可作为显示数据,也可用在调试语句中。
 
五、逃逸字符的问题
逃逸字符:在HTML编程中遇到“>”或“<”的话,浏览器会将它们作为HTML的保留字符,如标签的开始符和结束符来看待,这样就会出现一些错误。又如在JDBC编程中的sql语句中,如果出现了“””或者“’”等引号字符,也会出错,sql语句会把它们当作一个sql语句的开始或结束符。还有,如URL语句中的“?”等字符,也会造成URL表达式的混乱,等等。遇到了上面的这些情况,我们都自己找一些特殊字符对它们加以替换,然后用完后又替换回来,这些特殊的字符就是逃逸字符。但是去找逃逸字符比较麻烦,而且容易出错,易出现把逃逸字符张冠李戴的情况。
鉴于此,Jakarta Commons包为我们提供了一套关于逃逸字符的解决方案,使用这个方案,我们不需要自己亲自去查找逃逸字符,只需要调用Jakarta Commons包的API即可,如下所示:
String s = "There is always < (less) or > (more) than you want.";
String s1 = StringEscapeUtils.escapeHtml(s);
System.out.println(s1);
String s2 = StringEscapeUtils.unescapeHtml(s1);
System.out.println(s2.equals(s));
System.out.println(s2);
输出结果:
There is always &lt; (less) or &gt; (more) than you want.
true
There is always < (less) or > (more) than you want.
是不是很简单,我们只需要在上面的代码中引入Jakarta Commons的相应的包即可。
 
六、中英文拆字的问题
关于中英文混合句子拆字的问题,在bbs上看到一个解决方法,觉得很有意思。我们都知道,Java采用的是Unicode编码,所有的字符都占有一个字,两个字节。那么我们在一个中英文混合的句子中,怎么抽取出来一个个的汉语词语和英语单词呢?
下面就是一个简单的解决方法:
String s = "我是中ab国人";
        byte[] bt = s.getBytes();
        int i=0;
       while(i<bt.length){
               String ss;
               if(bt[i]<0){
                      ss = new String(bt,i,2);
                      i += 2;
               }
               else{
                      ss = new String(bt,i,1);
                      i++;
               }
               System.out.println(ss);
        }
输出结果为:



a
b


附:Java里面所有的字符(包括String, char)都是unicode编码的(例外的是,Character是32bit编码的,当然Java语言本身提供了转换机制),我们看到的每个字符,无论是中文还是英文(或者别的什么语言的字符),都可以用一个char来表示,所以,下面的代码段是一样的效果:
        String s = "我是中ab国人";
        for(int i = 0; i < s.length(); i ++)
            System.out.println(s.charAt(i));

关于那个Integer.toString(i)比""+i快的问题,应该是调用静态方法的原因,省了时间。
根据the Java Programming Language(4th Edition)
One special type of implicit conversion involves both the primitive and reference types: string conversion. Whenever a + operator has at least one String operand, it is interpreted as the string concatenation operator and the other operand, if not a String, is implicitly converted into aString. Such conversions are predefined for all primitive types.
因此,在这里+符号表示concatenation操作,右端的i作为非String类型的operand必须按照预先定义的方式进行转换。
查阅the Java Language Specification(3rd Edition),可以知道转换的细节:
A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression:
If T is byte, short, or int, then use new Integer (x).
所以""+i在执行时,由编译器隐式地调用new Integer(i),先生成一个Integer对象,再调用这个对象的toString()方法,得到+运算符需要的String对象;
Integer.toString(i)是一个static方法,由i直接获得String对象,不需要生成Integer对象,因此快许多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值