zoukankan      html  css  js  c++  java
  • java基础之字符串

    以下内容摘自《java编程思想》第十三章。

    1. 不可变 String

    String 对象是不可变对象,String 类中每一个看起来会修改 String 值的方法,实际上都是创建了一个全新的 String 对象,以包含修改后字符串的内容,而最初的 String 对象丝毫未动。看如下的代码:

    import static java.lang.System.*;
    
    public class Immutable{
    	public static String upcase(String s){
    		return s.toUpperCase();
    	}
    
    	/*
    		结果为:howdy HOWDY howdy
    	*/
    	public static void main(String[] args){
    		String q = "howdy";
    		out.println(q);
    		String qq = upcase(q);
    		out.println(qq);
    		out.println(q);
    	}
    }
    

    2. 重载 "+" 与StringBuilder

    String 是不可变的,这会带来一定的效率问题。首先看一下这段代码:

    public class Concatenation{
    	String mango = "mango";
    	String s = "abc"+mango+"def"+47;
    	System.out.println(s);
    	// 结果 abcmangodef47
    }
    

    可以想象一下,这段代码可能是这样工作的:String 可能有一个 append 方法,它会生成一个新的 String 类,以包含 “abc” 与 mango 连接后的字符串。然后,该对象再与 “def” 相连,生成另一个 String 对象,以此类推。

    这种工作方式当然行得通,但是为了生成最终的 String,此方式会产生大量的需要垃圾回收的中间对象,这样运行性能实在是糟糕。那么上面的代码是否真的是这样工作的呢?书中利用了 JDK 内置的工具 javap -c Concatenation 反编译上面的代码,发现,在上面的 "+" 操作中,编译器自作主张的使用了 StringBuilder 类,因为它更高效。每一次 "+" 操作,都调用了 StringBuilder.append 方法,最后使用 toString 方法返回字符串。

    上面对于 "+" 操作符工作流程的解释说明编译器会自动地优化性能,但是,它也不能做到完美,比如在循环中,经过循环一次, + 操作符就会产生一个 StringBuilder,所以,在循环中如果要对字符串进行操作,建议使用 StringBuilder 对象。

    StringBuilder 是 java SE5 引入的,在这之前 java 用的是 StringBuffer,后者是线程安全的,因此开销也会更大些,所以,在 java SE5/6 中,字符串操作应该会更快一点。

    3. 无意识的递归

    java 中每个类从根本上都是继承自 Object,标准容器类自然也不例外。因此容器类有 toString 方法,并覆写了该方法。例如 ArrayList.toString() 会遍历容器中所有的对象,并调用对象的 toString 方法。如果我们想要在 toString 方法中打印出对象的内存地址,也许会考虑使用 this 关键字。

    import java.util.ArrayList;
    import java.util.List;
    
    public class InfiniteRecursion {
    	public String toString(){
    		return "InfiiniteRecursion address"+this;
    	}
    	
    	public static void main(String[] args){
    		List<InfiniteRecursion> v = new ArrayList<InfiniteRecursion>();
    		for(int i=0;i<10;i++){
    			v.add(new InfiniteRecursion());
    		}
    		System.out.println(v);
    	}
    }
    

    但是上面的代码运行会出现 java.lang.StackOverflowError,这是为什么呢?原因出现在 toString 方法中,编译器看到字符串 "InfiiniteRecursion address" 后面跟着一个 "+" ,而再后面的对象不是 String,于是编译器试着将 this 转换为 String 对象,怎么转换呢?这是通过调用 toString 方法,于是就发生了递归调用。如果在上面的例子中想要打印出对象的内存地址,应该调用 super.toString 方法。

    以上是我对书中的一些总结,有什么好的看书建议欢迎提出来一起交流分享。

  • 相关阅读:
    svn 指定不更新目录
    C# 修改win环境变量 来加载dll库
    基本组件
    在SD卡上创建/删除文件夹 使用DDMS透视图管理SD卡
    linux中图形界面改成文本
    表格布局和线性布局
    文件操作
    静态库的生成和调用
    船载电子海图系统(E C S )概述
    GPS全球定位系统构成及原理
  • 原文地址:https://www.cnblogs.com/firepation/p/9481883.html
Copyright © 2011-2022 走看看