• String类浅谈


    String源码学习

    String类被final修饰,实现了Serializable、CharSequence(实现类有:String、StringBuilder、StringBuffer。有length()和charAt等方法方法)、Comparable<String>接口。

    成员变量

    private final char value[];
    private int hash; // Default to 0

    1、常用方法

    hashCode();

    获得字段的hash值

    equals();

    重写了Object的equals()方法。

    除了做地址比较,还做了字符的逐一比较,但是要求传入对象是一个String类型的值,否则会返回false。

    contentEquals(CharSequence cs);
    用于charSequence接口实现类值是否相等的比较。也就是通用与StringBuffer、StringBuider和String的equals比较。

     compareTo();

     实现了Comparable<String> 接口,重写了compareTo()接口 并且还多加了一个compareToIgnoreCase()方法。

    字符串不同,返回第一个不相同的charASCII码值的差值,否则返回字符串长度差值

    trim();

     去除字符串前后空字符,开启两个while循环,char[i] <= ' '被去掉,' '的ASCII码值是32,是字符ASCII的开始,32之前的是控制符、通信专用字符的ASCII码值。

      如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BS(退格)、BEL(响铃)等;

      通信专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等;

    关于忽略大小写的比较和equals方法,其中使用到了Character类的toUpperCase和toLowerCase方法。其底层通过二进制的按位与运算获得字母大小写转化。

     

    indexOf()

    laseIndexOf()

    substring()

    split()

    字符串截取

    concat()

    创建一个数组,先把当前字符串value复制进去,再通过getChars把传入字符串的value复制到char数组里,底层都是调用了System.arragcopy方法(native修饰的本地方法)。

     

    public native String intern();

     获得字符串对应的常量池中的字符串值。

    一般用作通过new String()获得字符串时,获取常量池字符串位置。

    new的方式创建对象,会去堆上创建个对象,然后再将对象的引用指向常量池对应的常量。

    public static String valueOf(double d)
    public static String valueOf(float f)
    public static String valueOf(long l)
    public static String valueOf(int i)

    indexOf():查询字符串首次出现的下标位置
    lastIndexOf():查询字符串最后出现的下标位置
    contains():查询字符串中是否包含另一个字符串
    toLowerCase():把字符串全部转换成小写
    toUpperCase():把字符串全部转换成大写
    length():查询字符串的长度
    trim():去掉字符串首尾空格
    replace():替换字符串中的某些字符
    split():把字符串分割并返回字符串数组
    join():把字符串数组转为字符串

    2、相关知识

    StringBuilder

    StringBuffer

    StringBuilder和StringBuffer是应对String被final修饰后做字符串拼接的封装类

    两者都继承了AbstractStringBuilder类,实现了CharSequence方法,基本的字符串功能都是在AbstractStringBuilder里实现的,不通点在于,java对所有的StringBuffer操作,都加了synchronized修饰。

     

    3、常见问题

    为什么 String 类型要用 final 修饰?

    Java 语言之父 James Gosling 的回答是,他会更倾向于使用 final,因为它能够缓存结果,当你在传参时不需要考虑谁会修改它的值;如果是可变类的话,则有可能需要重新拷贝出来一个新值进行传参,这样在性能上就会有一定的损失。

    James Gosling 还说迫使 String 类设计成不可变的另一个原因是安全,当你在调用其他方法时,比如调用一些系统级操作指令之前,可能会有一系列校验,如果是可变类的话,可能在你校验过后,它的内部的值又被改变了,这样有可能会引起严重的系统崩溃问题,这是迫使 String 类设计成不可变类的一个重要原因。

    总结来说,使用 final 修饰的第一个好处是安全;第二个好处是高效,以 JVM 中的字符串常量池来举例,如下两个变量:

    String s1 = "java";
    String s2 = "java";
    只有字符串是不可变时,我们才能实现字符串常量池,字符串常量池可以为我们缓存字符串,提高程序的运行效率,如下图所示:

    == 和 equals 的区别是什么?
    String 和 StringBuilder、StringBuffer 有什么区别?
    String 的 intern() 方法有什么含义?
    String 类型在 JVM(Java 虚拟机)中是如何存储的?编译器对 String 做了哪些优化?

    String 常见的创建方式有两种,new String() 的方式和直接赋值的方式,直接赋值的方式会先去字符串常量池中查找是否已经有此值,如果有则把引用地址直接指向此值,否则会先在常量池中创建,然后再把引用指向此值;而 new String() 的方式一定会先在堆上创建一个字符串对象,然后再去常量池中查询此字符串的值是否已经存在,如果不存在会先在常量池中创建此字符串,然后把引用的值指向此字符串,如下代码所示:

    String s1 = new String("Java");
    String s2 = s1.intern();
    String s3 = "Java";
    System.out.println(s1 == s2); // false
    System.out.println(s2 == s3); // true
    它们在 JVM 存储的位置,如下图所示:

     JDK 1.7 之后把永生代换成的元空间,把字符串常量池从方法区移到了 Java 堆上,除此之外编译器还会对 String 字符串做一些优化,将常用字符拼接不再创建多个常量池常量。

    String s1 = "Ja" + "va";
    String s2 = "Java";
    System.out.println(s1 == s2);

  • 相关阅读:
    FiddlerCoreAPI 使用简介
    fiddler script建议教程
    PDF文本内容批量提取到Excel
    pymc_实现贝叶斯统计模型和马尔科夫链蒙塔卡洛
    贝叶斯
    Logistic Ordinal Regression
    逻辑回归原理_挑战者飞船事故和乳腺癌案例_Python和R_信用评分卡(AAA推荐)
    逻辑回归实战--美国挑战者号飞船事故_同盾分数与多头借贷Python建模
    python操作mysql数据库
    多元回归比一元回归优越性
  • 原文地址:https://www.cnblogs.com/tianhaichao/p/16466491.html
Copyright © 2020-2023  润新知