4.2String类

这一节,我们学习第一个类:String类。String翻译成汉语就是“字符串”,是字符的序列。我们知道,在Java中,默认采用Unicode字符集,因此字符串就是Unicode字符的序列。例如字符串“Java大失叔”,就是由7个Unicode字符‘J’、‘a’、‘v’、‘a’、‘大’、‘失’、‘叔’组成。在JDK中,把字符串抽象成一个类String提供给我们使用。String类在java.lang包中。

4.2.1构造String对象

  上面我们说了,想看电视得先买一台电视,电视在出厂的时候厂家会初始化它的状态。想使用String类,得先得到一个String的对象,然后指定属性的初始状态,然后才能使用它。得到对象的过程,叫做构造对象。在Java中,我们用构造器(constructor)来构造实例,构造器其实是一种特殊的方法,用来构造并初始化对象。我们采用在构造器前面加上new关键字来实现,例如:

new 构造器();

我们查看String类的API文档(怎么查这里不再赘述),构造方法截图如下:

发现String类的构造方法有几个特点:

  • 足足有15个构造方法

  • 有的方法上标有Deprecated,这个标签的含义是不推荐使用,将来在新版本中可能会移除

  • 构造方法的名字和类名相同

构造方法的名字和类名相同,这是Java构造器的特点,也是规定。我们挑选其中一个构造方法:String(char[] value)

我们看到,这其实就是用一个char数组来构造一个字符串,那么首先我们得有一个char数组才行,例如我们想要得到一个字符串“Java大失叔,你真棒”。那么代码如下:

char[] a = { 'J', 'a', 'v', 'a', '大', '失', '叔', ',', '你', '真', '棒' };String s = new String(a);System.out.println(s);// 结果输出:Java大失叔,你真棒

事实上,由于String太常用了,Java给我们提供了更加简便的构造方法,直接用双引号将一段字符序列包起来,就得到了一个String的实例:

String s = "Java大失叔,你真棒";

OK,我们得到了一个String对象了,下面我们来使用这个对象。我们可以看到,API中有几十个方法,我们挑选一些常用的演示一下。

4.2.2代码点和代码单元

首先,我们回忆一下关于char和Unicode的知识。Unicode定义了U+0000到U+10FFFF一共1114112个码位(code point),英文直译为代码点。一个代码点表示一个字符。char是用来存放UTF-16编码中的一个代码单元(code unit),即2个字节。平面0的代码点用一个代码单元即一个char就可以表示,其余的代码点需要用2个代码单元即2个char才能表示。

我们知道Stirng是Unicode字符的序列,但是底层的实现实际上是用char构成的。String类提供了一些关于代码点和代码单元相关的方法,请看下面摘抄的几个方法:

修饰和类型

方法

描述

int

length()

返回字符串的长度

int

codePointCount(int beginIndex, int endIndex)

返回beginIndex和endIndex-1之间的代码点的数量。

char

charAt(int index)

返回index索引处的char

int

codePointAt(int index)

返回index索引处的代码点

我们想获得字符的数量(即代码点的数量),需要用codePointCount方法,而length方法返回的是char的数量(即代码单元的数量)。调用对象的方法很简单,用如下形式:

对象.方法();

代码示例如下:

String s = "大失叔喜欢打麻将??????";//  System.out.println("字符串s的代码单元数量为:" + s.length());System.out.println("字符串s的代码点数量为" + s.codePointCount(0, s.length()));

输出结果:

字符串s的代码单元数量为:20  字符串s的代码点数量为:14

我们可以看到,对于??????,这6个字符,每个字符占用2个代码单元,所以length方法的结果是20,而codePointCount方法的结果是14。

我们再看看后面2个方法,这应该就相对简单了,一个是返回index处的代码单元,一个是返回index处的代码点。我们直接看代码:

String s = "大失叔喜欢打麻将??????";//  int c = s.charAt(8);// 把char赋值给一个int,对应这个代码单元对应的十进制,结果是55356,十六进制为0xD83Cint d = s.codePointAt(8);// 结果是126976,十六进制为0x1F000

4.2.3对象与变量

上面我们看到,创建出来一个String对象,一般我们会赋值给一个变量。那么对象和变量之间有什么关系和区别呢?我们先看几行代码:

String a;String b;a = "大失叔喜欢打麻将";b = a;

这几行代码,会涉及到下面一些行为:

  • 第1、2行,我们定义了2个String类型的变量a和b。这时候Java会在内存中分别分配一块空间给a和b,但是这时候这2块内存空间中没有存放任何值。

  • 第3行,我们把一个字符串赋值给变量a。Java会在内存中分配一块空间,存放这个字符串,然后把这块空间的地址存放到变量a的内存空间中。

  • 第4行,把变量a赋值给b,相当于把变量a内存空间中的地址存放到变量b的内存空间中,这时候a和b同时指向字符串“大失叔喜欢打麻将”对应的内存空间。

我们用一张图示意如下:

我们需要牢牢记住一点:在Java中,任何对象的值都是存放在堆内存中的,而对象类型的变量对应的内存中保存的是对象的内存地址,我们称之为对象引用。因此new操作符返回的结果其实是一个引用。

我们可以显式的把一个对象变量设置为null,这时候该变量的内存存放的将是空值,表明它不引用任何对象。如果我们对一个值为null的变量进行方法调用,程序在运行时则会抛出异常。

4.2.4字符串拼接

在Java中,字符串的拼接有一种很简单的方法,就是用加号(+)连接两个字符串,结果会构造出一个新的字符串对象。我们看代码:

String a = "Java大失叔";String b = "喜欢打麻将";String c = a + b;System.out.println(c);// 结果将输出:"Java大失叔喜欢打麻将"

在这段代码中,堆内存中将会分配3块空间,分别对应字符串"Java大失叔"、"喜欢打麻将"、" Java大失叔喜欢打麻将"。我们用一张图来演示这个过程:

我们还可以将一个字符串和一个非字符串用+连接起来,这时候非字符串对象会被转换为字符串(具体如何转换,后续会详细探讨)。例如:

String a = "Java大失叔卡里只有";int b = 200;String c = "元钱了";System.out.println(a + b + c);// 结果将输出:Java大失叔卡里只有200元钱了

String类的API中还提供了一个方法concat用来拼接字符串,方法摘抄如下:

修饰和类型

方法

描述

String

concat(String str)

将str拼接在本字符串后面

使用起来也很简单,代码如下:

String a = "Java大失叔";String b = "喜欢打麻将";String c = a.concat(b);System.out.println(c);// 结果将输出:Java大失叔喜欢打麻将

有的时候,需要将很多个字符串拼接成一个大字符串,这时,如果用+的方式,不是很合适了。因为用+的方式,每次都会构建一个新的对象,比较耗时,还占内存,效率比较低。好在Java提供了另外一种方式,就是采用StringBuilder类和StringBuffer类。一般情况下我们都会采用StringBuilder类,因为它的效率略高。而Stringbuffer类是线程安全的,关于线程会在后面专门讨论。这2个类的API几乎完全一样。用StringBuilder非常简单,代码演示如下:

StringBuilder sb = new StringBuilder();// 首先构建StringBuilder对象sb.append("Java");// 然后用append方法添加小字符串sb.append("大失叔");sb.append("太帅了");String s = sb.toString();// 最后调用toString()方法,返回一个字符串对象System.out.println(s);// 结果将输出:Java大失叔太帅了
其实append方法返回的依然是StringBuilder对象,因此还可以采用一种更为简洁的方式:
String s = new StringBuilder().append("Java").append("大失叔").append("太帅了").toString();System.out.println(s);// 结果将输出:Java大失叔太帅了
关于加号、concat、StringBuilder这三者的比较,笔者给出如下结论:
  1. 对于拼接少量的字符串,用哪种方式都差不多,加号书写起来更加方便。笔者几乎没用过concat方法。

  2. 加号和StringBuilder都可以拼接非字符串类型(可以查看API,有很多个append方法)。

  3. 对于需要拼接多个字符串的时候,强烈建议使用StringBuilder。(笔者在早年编写一个网络程序的时候,吃过亏)

4.2.5字符串截取和比较

关于字符串还会经常使用比较和截取的方法,先列出方法如下:

修饰和类型

方法

描述

boolean

startsWith(String prefix)

检查字符串是否以指定的前缀prefix开始

boolean

endsWith(String suffix)

检查字符串是否以指定的后缀suffix结尾

String

trim()

删除字符串前后的空白,并返回一个新字符串

boolean

equals(Object anObject)

检测2个字符串是否相等

boolean

equalsIgnoreCase(String anotherString)

检测2个字符串在忽略大小写的情况下是否相等

String

substring(int beginIndex)

截取从beginIndex到末尾的字符串并返回

String

substring(int beginIndex, int endIndex)

截取从beginIndex到endIndex的字符串并返回,不包括endIndex

我们经常会比较一个字符串是否以某个字符串开头或结尾,代码如下:

String a = "Java大失叔";boolean b1 = a.startsWith("Java");// 结果为trueboolean b2 = a.startsWith("java");// 结果为falseboolean b3 = a.endsWith("叔");// 结果为true

有时候,经过网络传输后的字符串经常前后会带一些空白,眼睛又看不见,很不利于比较,会用trim方法去掉前后的空白:

String a = "   Java大失叔       ";String b = a.trim();System.out.println(b);// 结果将输出:Java大失叔

需要注意,这里的空白指的是Unicode编码小于或等于”\u0020”的字符。

对于字符串的截取,用subString方法将非常方便:

String a = "Java大失叔 ";String b = a.substring(4);// 结果是:大失叔String c = a.substring(2, 6);// 结果是:va大失

这里要注意的是,返回的结果字符串是包括beginIndex位置的代码单元,但是不包括endIndex位置的代码单元。

比较2个字符串是否相等,用equals方法,如果相等返回ture,否则返回false。如果想不区分大小写比较是否相等,则可以使用equalsIgnoreCase方法。表达式为:

a.equals(b)

其中,a和b即可以是变量,也可以是字符串常量。

String a = "Java大失叔";String b = "java大失叔";System.out.println(a.equals(b));// 结果为falseSystem.out.println(a.equalsIgnoreCase(b));// 结果为trueSystem.out.println("JAVA大失叔".equalsIgnoreCase(b));// 结果为true

这里需要特别注意,千万不能用==运算符来比较2个字符串是否相等。因为==运算符比较的是2个字符串是否存放在同一个内存位置上。但是事实上,对于2个字符内容完全一样的字符串,是很有可能存放在不同的内存空间的,因此用==比较结果将为false。这个问题Java新手经常会犯。

最后我们很容易发现,String的API中没有提供修改字符串内容的方法。这其实是因为String类被定义为final的(关于final后面也会介绍),我们看一下String的源代码(在Eclipse中,可以很轻松的查看源代码,鼠标移动的任意一个String字符上,按住Ctrl键后,点击鼠标左键):

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence

用final修饰一个类后,这个类的对象将不能被修改。

String类提供了50个多个方法,这些方法都很有用,但是我们不可能记住所有的方法名和参数要求,这里还有一个Eclipse的小技巧,当我们敲完变量名加“点”后,Eclipse会自动弹出提示,或者还可以用Ctrl+/自动补全,如下图:

c++ char 转 string_4.2String类相关推荐

  1. char数组转string_String类和其它数据类型的相互转换

    对于上面的这些包装类,除了Character以外,都有可以直接使用字符串参数的构造函数,这也就使得我们将String类转换为这些数据类型变得相当之简单,即: Boolean(String s).Int ...

  2. java 调用弗雷_JAVA API(一)String类和StringBuffer类

    1.String类和StringBuffer类 在程序中经常会用到字符串,所谓的字符串就是指一连串的字符,它是由多个单个字符连接而成的.字符串中可以包含任意字符,这些字符必须包含在一对双引号" ...

  3. 菜鸟学JAVA之——常用类(StringBuffer、StringBuilder、Comparable、Comparator等)

    文章目录 常用类 字符串相关的类 一.String类及常用方法 二.StringBuffer.StringBuilder JDK 8 之前的日期时间API 一.System静态方法 二.Date类 三 ...

  4. 【String类和标准模板库】

    1.string类 2.智能指针模板类 3.标准模板库 4.泛型编程 5.函数对象 6.算法 7.其他库 1.string类 string类是由头文件string支持的,要使用类,关键要知道它的公有接 ...

  5. 第二次预习——java异常类和常用类 容器

    文章目录 一.异常类 1.概念 2.异常类分类 2.1分类 2.2Error与Exception的区别 2.3Java中常见运行时异常 3.try-catch语句 3.1用法 3.2语句 3.3实例 ...

  6. 《C++中STL引入和string类常用接口+自我实现-》

    前言 在这篇博客里将详细说说C++中的STL,通过这篇我们可以学习到什么是STL,以及STL的六大组件,STL具有的缺陷,最后看看string类及面试会让模拟实现string类的操作. 文章目录 前言 ...

  7. 七:Object:常用类

    七:Object:常用类 7.1克隆方法clone() 格式: 类名.clone(); protected Object clone() throws CloneNotSupportedExcepti ...

  8. java笔记——Java常用类

    目录 目录 Java常用类目标 1.1内部类 1.2成员内部类 1.3静态内部类 1.4匿名内部类 2.Object类 2.1getClass()方法 2.2hasCode() 2.3toString ...

  9. 第11-15章枚举|异常|常用类|集合|泛型

    文章目录 第11章 枚举和注解 11.1举例 11.2枚举的二种实现方式 11.3enum 实现接口 11.4注解的理解 11.4基本的 Annotation 介绍 第12章 异常-Exception ...

最新文章

  1. quartz与c3p0冲突
  2. 白话Elasticsearch20-深度探秘搜索技术之使用rescoring机制优化近似匹配搜索的性能
  3. 深入理解 python 中的赋值、引用、拷贝、作用域
  4. AOP 中必须明白的概念-切入点(Pointcut)
  5. CNN结构:SPP-Net为CNNs添加空间尺度卷积-神经元层
  6. Array的sort方法
  7. 蓝桥杯2017初赛-迷宫-dfs
  8. python的仿真效果好吗_Python SimPy 仿真系列 (1)
  9. linphone-android移植
  10. SimpleDet: 一套简单通用的目标检测与物体识别框架
  11. Kafka学习之(四)PHP操作Kafka
  12. Centos7搭建maven私服nexus3,互联网大厂100道Java面试题助你冲关金三银四
  13. n6 tenda 固件_腾达 Tenda N6 刷 TTDW 说明
  14. Android ADB 环境变量配置
  15. android 涨潮动画加载_潮汐apk客户端-潮汐android最新版APP下载v2.0.1.1 免费版-腾牛安卓网...
  16. 通过ajax获取对象后动态插入文本框
  17. 内存颗粒位宽和容量_SDRAM内存模组的物理Bank与芯片位宽(高手进阶,终极内存技术指南——完整/进阶版)...
  18. 数据结构与算法 python版 之 递归三定律
  19. 常用的几种设计模式详解
  20. 100道Java并发和多线程面试题

热门文章

  1. iis只能访问html页面,win2003 IIS6,能访问html页 但是不能访问aspx页解决办法汇总
  2. oracle判断数据表的字段内容是否为空
  3. android+mysql+server+error_Lost connection to MySQL server during query错误 | 学步园
  4. php7.0康乐安装_Linux环境PHP7.0安装
  5. python文件输出中文_【python】中文的输出,打印,文件编码问题解决方法
  6. Springboot整合RabbitMq-用心看完这一篇就够了(最新)
  7. c 和 java 差异_java和C/C++的差异是什么
  8. 电脑怎么下mcjava版_游戏下载常见问题(苹果、电脑玩家下载须知)
  9. 涉密计算机格式化维修,涉密计算机的涉密信息被删除或格式化后,通过一定的技术手段仍可以复原,连接互联网易造成泄密。()...
  10. 【Zabbix】使用dbforbbix 2.2-beta监控Redhat 7.0上的Oracle、Mysql