zoukankan      html  css  js  c++  java
  • String 字符串对象

    String是什么

    String字符串,是一种引用数据类型,并不是基础数据类型。

    对于基础数据类型和引用数据类型的区别:

    基础数据类型,在创建时直接将值存放在栈内存中。

    引用数据类型,在创建时栈内存中存放一个引用,这个引用存放的是堆内存的位置,而堆内存中就是存放具体的值。

    举例说明:

    假如String对象是一个储物柜,在使用储物柜时(相当于新建一个String对象),

    我们需要会得到一张记着储物柜的小票(小票相当于栈内存空间,小票上保存引用),

    凭借这张小票就可以找到储物柜,然后拿到储物柜中存放的东西(储物柜相当于堆内存空间,可以根据引用去得到堆内存中的值)。

    对于基础数据类型,则是直接将值写在小票上。

    String的底层数据结构

    String的底层实现是字符数组,这一点可以在源码中看到,

    其中属性 private final char value[]; 就是用来存储String的值,

    以下是String类的部分源码:

     1 public final class String
     2     implements java.io.Serializable, Comparable<String>, CharSequence {
     3     /** The value is used for character storage. */
     4     private final char value[];
     5 
     6     /** Cache the hash code for the string */
     7     private int hash; // Default to 0
     8 
     9     /** use serialVersionUID from JDK 1.0.2 for interoperability */
    10     private static final long serialVersionUID = -6849794470754667710L;

    String类被final修饰,则表示String类不可以被继承。

    String类的value属性使用了 final 进行修饰,则表示value是一个常量,常量不可以更改。

    String对象的重新赋值

    String类的源码中可以看到String类的value属性使用了 final 进行修饰,既然是常量。

    在发生对象需要重新赋值的时候,String的做法是,将String对象的栈内存与堆内存的引用断开。

    再将栈内存中的引用指向新的堆内存空间。

    本质上就是新建一个String对象。

    由此可以引发一个问题,如果代码中频繁出现对String对象的重新赋值意味着会有大量的堆内存被弃用。

    这部分被弃用的堆内存空间只能通过垃圾回收机制进行回收,这会降低内存的利用率。(浪费内存是一方面,另一方面垃圾回收也会耗费资源。此问题在面试中出现的概率比较高)

    这个问题可以通过使用StringBuffer或者StringBuilder来解决(StringBuffer和StringBuilder会在接下来的文章进行介绍)。

    以下是《Java开发实战经典》一书中的示例:

    String对象的比较

    比较方式分为两种(自定义比较方法除外):

    a.双等号(==):双等号的判断依据是对象的堆内存地址是否相同。(用上面储物柜的例子就是同一个储物柜,当然放的是同样的东西)

    b.使用方法equals(Object anObject):方法比较的是对象的取值。

    String类中equals(Object anObject)方法源码:

     1     public boolean equals(Object anObject) {
     2         if (this == anObject) {
     3             return true;
     4         }
     5         if (anObject instanceof String) {
     6             String anotherString = (String)anObject;
     7             int n = value.length;
     8             if (n == anotherString.value.length) {
     9                 char v1[] = value;
    10                 char v2[] = anotherString.value;
    11                 int i = 0;
    12                 while (n-- != 0) {               //通过while循环比较字符数组中的值
    13                     if (v1[i] != v2[i])
    14                         return false;
    15                     i++;
    16                 }
    17                 return true;
    18             }
    19         }
    20         return false;
    21     }

    以下是代码示例:

    public class TestString {
        public static void main(String[] args) {
            String str1 = "a";
            String str2 = "a";
            String str3 = new String("a");   //使用new关键词创建String对象
            String str4 = "b";
            
            System.out.println("str1  ==    str2: "+(str1 == str2));
            System.out.println("str1 equals str2: "+(str1.equals(str2)));
            System.out.println("str1  ==    str3: "+(str1 == str3));
            System.out.println("str1 equals str3: "+(str1.equals(str3)));
            System.out.println("str1  ==    str4: "+(str1 == str4));
        }
    }

    控制台结果:

    str1  ==    str2: true
    str1 equals str2: true
    str1  ==    str3: false
    str1 equals str3: true
    str1  ==    str4: false

    通过 str1 == str2: true 结果得出的结论:

    String类在不使用new 关键词来新建对象时,如果str1 和 str2 的取值相同,

    并不会为str1 和 str2 分别开辟堆内存空间,而是将str1 和 str2同时指向同一个堆内存,减少内存浪费。

    String类常用方法

    以下是《Java开发实战经典》一书中表格:

    结语

    纸上得来终觉浅,绝知此事要躬行。

    String类中的内容很多,单构造方法就是十多种。

    虽然内容多,但是难度都不高可能花看一个小视频的时间能看完。

    这里对String类进行简单的介绍。

  • 相关阅读:
    CSS margin的一些让你模糊的点
    VUE中CSS样式穿透
    如何给img标签里的请求添加自定义header?
    iframe的父子页面进行简单的相互传值
    Docker部署网站之后映射域名
    机器学习笔记(九)---- 集成学习(ensemble learning)【华为云技术分享】
    鲲鹏性能优化十板斧之前言 | 鲲鹏处理器NUMA简介与性能调优五步法
    【我的物联网成长记8】超速入门AT指令集【华为云技术分享】
    【直播分享】实现LOL小地图英雄头像分析案例【华为云分享】
    MongoDB一次节点宕机引发的思考(源码剖析)【华为云分享】
  • 原文地址:https://www.cnblogs.com/chaojizhengui/p/10789155.html
Copyright © 2011-2022 走看看