小瓜牛漫谈 — String


String 类在 Java 中代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。

public static void main(String[] args) {
     
     String str1 = "abc";
     String str2 = new String("cde");
     System.out.println(str1);
     System.out.println(str2);
 }

在上面代码中, 第 4 行实际上创建了两个 String 对象, 一个是 "cde" 本身, 另外一个则是由 new 关键字为对象申请开辟的内存空间。

[ 可结合文章最下面给出的第 10 条来理解 ]

通常, 使用 String(String original) 构造器来创建 String 对象要比直接使用字符串字面值的开销更加的大。


String 字符串是常量, 它们的值在创建之后不能够被更改:

package net.yeah.fancydeepin.string;
 
 public class Application {
 
     public static void main(String[] args) {
         
         String str = "abc";
         str += "cde";
         System.out.println(str);
     }
 }

当程序运行时, JVM 内存中的分配看起来应该像:


从上面的图来看, str 最初引用的是 "abc" 对象, 最终打印输出的结果是 abccde, 这并不是说 str 所引用的对象的内容发生了变化,

而是 str 在执行的过程中重新引用了另外的一个 String 对象 "abccde"。


可以使用 java 自带的反编译工具 javap 来查看编译后的字节码文件信息:  javap -c Appliaction


从上面的图来看:

第 0 行, 将常量池中的 "abc" 对象压栈;

第 8 行, 调 String.valueOf(Object obj) [ 实际上是将 str 转成了 String 对象 ];

第 3、11 行, 是在创建 StringBuilder 对象, 通过 StringBuilder(String str) 构造器 [ 参数是第 8 行的 String 对象 ];

第 14 行, 将常量池中的 "cde" 对象压栈;

第 16 行, 调 StringBuilder 的 append 方法 [ 将 "cde" 拼在 "abc" 的后面 ];

第 19 行, 调 StringBuilder 的 toString() 方法。


使用 jad 工具, 可以更加容易的去读懂编译后的字节码文件内容: jad -o -a -s .java Application.class


结合上面的图可以看出, 在 java 中, 通过使用 "+" 符号来串联字符串的时候, 实际上底层会转成通过 StringBuilder 实例的 append() 方法来实现。

[ 关于对 String 类使用 "+" 符号来串联字符串, 在文章最下面的第 10 条继续来补充。 ]


String 类常用方法: 

1> startsWith(String prefix)、endsWith(String suffix)

startsWith(prefix) 测试字符串是否是以指定的前缀 prefix 开始, endsWith(suffix) 测试字符串是否是以指定的后缀 suffix 结束:

public static void main(String[] args) {
     
     String url = "/small-snail/archive/20130421.html";
     System.out.println(url.startsWith("/small-snail/archive/")); //true
     System.out.println(url.endsWith(".html")); //true
     System.out.println(url.startsWith("/small-snail/category/")); //false
     System.out.println(url.endsWith(".php")); //false
 }

2> equals(Object anObject)

在 java 中, Object 是一个顶级类, 所有类都直接或间接或默认的继承了该类。

Object 类有一个 equals(Object obj) 方法, 因此, 所有类都默认的拥有了这个方法。

但 Object 的 equals(obj) 方法默认比较的是两个引用变量所引用的对象是否相同, 只有当两个引用变量引用了相同的一个对象的时候才会返回 true。

String 类重写了 Object 类的此方法, String 类的 equals 方法比较的是两个 String 对象的内容是否相同。 

package net.yeah.fancydeepin.string;
 
 public class Application {
 
     public static void main(String[] args) {
 
         String kitty1 = new String("HelloKitty");
         String kitty2 = new String("HelloKitty");
         StringBuilder kitty3 = new StringBuilder("HelloKitty");
         System.out.println(kitty1.equals(kitty2));  //true
         System.out.println(kitty1.equals(kitty3));  //false
     }
 }
第 11 行, 虽然 kitty3 的内容与 kitty1 的内容一样, 但由于 kitty3 不是一个 String 对象, 因此调 equals 方法的返回值为 false。

3> equalsIgnoreCase(String anotherString)

比较两个 String 对象的内容是否相同, 忽略大小写。

public static void main(String[] args) {
      
     String param1 = "helloKitty";
     String param2 = "HelloKitty";
     System.out.println(param1.equals(param2));  //false
     System.out.println(param1.equalsIgnoreCase(param2));  //true 
 }

4> getBytes(String charsetName)、String(byte[] bytes)

getBytes(String charsetName) 是使用指定的字符集 charset 将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。

package net.yeah.fancydeepin.string;
 
 import java.io.UnsupportedEncodingException;
 
 public class Application {
 
     public static void main(String[] args) throws UnsupportedEncodingException {
 
         String param = "哈喽Kitty";
         String charset;
         
         charset = new String(param.getBytes("GBK")); //乱码
         System.out.println(charset);
         
         charset = new String(param.getBytes("GB2312")); //乱码
         System.out.println(charset);
         
         charset = new String(param.getBytes("ISO-8859-1")); //乱码
         System.out.println(charset);
         
         charset = new String(param.getBytes("UTF-8")); //正常
         System.out.println(charset);
         
         charset = new String(param.getBytes("UTF-16")); //乱码
         System.out.println(charset);
     }
 }

上面给出来的是 java 开发过程中比较经常遇到的字符集编码。当一个字符串中含有中文字符的时候, 如果该字符串在编码和解码前后所使用的字符编码不一致,

就会导致中文乱码的问题。

由于我的 eclipse SDK 工作区所使用的是 UTF-8 编码, 所以上面只有 "UTF-8" 字符编码输出的内容是正常的, 其他情况就会出现中文乱码的问题。

5> getBytes(String charsetName)、String(byte[] bytes, String charsetName)

上面示例中出现了中文乱码问题, 其实现在网络上关于中文乱码这点事儿, 资料已经是非常的多了。下面接下来将首先模拟出一个中文乱码的问题, 然后来解决它:

package net.yeah.fancydeepin.string;
 
 import java.io.UnsupportedEncodingException;
 
 public class Application {
 
     public static void main(String[] args) throws UnsupportedEncodingException {
 
         String param = "哈喽Kitty";
         
         param = new String(param.getBytes("UTF-8"), "ISO-8859-1"); //中文乱码
         System.out.println(param);
         
         //解决中文乱码
         param = new String(param.getBytes("ISO-8859-1"), "UTF-8"); //恢复正常
         System.out.println(param);
     }
 }

param = new String(param.getBytes("UTF-8"), "ISO-8859-1"); 意思是说:

将 param 以 UTF-8 编码方式去编码, 然后再按 ISO-8859-1 编码方式去解码编码后的内容, 来构造一个新的 String 对象 param。

由于 param 原本是按 UTF-8 编码方式编码出来的, 现在却使用 ISO-8859-1 编码方式去解码, 这个时候出现中文乱码是很正常的事情。

再者, ISO-8859-1 的编码方式本身是不支持中文的。

解决中文乱码问题, 无非就是使用正确的字符集编码去解码字符串的内容:

param = new String(param.getBytes("ISO-8859-1"), "UTF-8");

首先是将 param 以 ISO-8859-1 的编码方式编码出来, 因为在 java 的 JVM 中, 任何 String 都是一个 unicode 字符串,

接着再使用 UTF-8 去解码, 这个时候的中文就不再是乱码啦。。

 

为了避免引起误解, 补充说明一下, 上面不是一定要使用与 IDE 相同的编码方式 UTF-8 才不会引起中文乱码, 实际上也可以换成 GBK、GB2312 等兼容中文的

编码方式也是可以的, 只需要保证编码和解码使用的是相同的字符集编码方式即可。


6> indexOf(String str)、lastIndexOf(String str)、substring(int beginIndex, int endIndex)

indexOf 用于返回指定的子字符串在主字符串中第一次出现处的索引值; lastIndexOf 用于返回指定的子字符串在主字符串中最后一次出现处的索引值。

substring 则是用来切割主字符串, 根据开始索引值和结束索引值切割并返回一个新字符串。

package net.yeah.fancydeepin.string;
 
 public class Application {
 
     public static void main(String[] args) {
          
         String param = "archive.logo.ico";
         int firstIndex = param.indexOf("a");
         int lastIndex = param.lastIndexOf("o");
         int length = param.length();
         System.out.println(firstIndex);  // 0
         System.out.println(lastIndex);   // 15
         System.out.println(length);      // 16
         System.out.println(param.substring(firstIndex, lastIndex)); // archive.logo.ic
         param = param.substring(param.lastIndexOf("."), length);    // .ico
         System.out.println(param);
     }
     
 }

从上面代码可以看出, 索引值是从 0 开始的, substring(beginIndex, endIndex) 方法切割字符串的区间其实是左闭右开: [ beginIndex, endIndex )

7> replaceAll(String regex, String replacement)

用子字符串 replacement 来替换主字符串中所有由正则表达式 regex 匹配的子字符串。

package net.yeah.fancydeepin.string;
 
 public class Application {
 
     public static void main(String[] args) {
          
         String packageName = Application.class.getPackage().getName();
         
         String packagePath1 = packageName.replaceAll(".", "/");  //将所有的字符换成了'/'
         System.out.println(packagePath1); // 打印 ///
         
         String packagePath2 = packageName.replaceAll("\\.", "/");  //将所有的'.'换成'/'
         System.out.println(packagePath2);  // net/yeah/fancydeepin/string
         
         String packagePath3 = packageName.replaceAll("e+", "E");  //凡是出现'e'一次或以上的用'E'替换
         System.out.println(packagePath3);  // nEt.yEah.fancydEpin.string
     }
     
 }

上面代码中需要注意的是 packagePack1, replaceAll 的第一个参数使用的是正则表达式, 正则表达式中的 '.' 可以匹配除“\n”之外的任何单个字符,

因此 packagePath1 打印输出的全是反斜杠'/', 如果要匹配'.', 则应该使用转义字符, 像上面代码中的 packagePath2。

8> split(String regex)

根据给定的正则表达式 regex 将主字符串拆分成一个字符串数组。

package net.yeah.fancydeepin.string;
 
 public class Application {
 
     public static void main(String[] args) {
          
         String param = "Java,Android,PHP,C,C++,C#";
         String[] languages = param.split(",");
         for(String language : languages){
             System.out.println(language);
         }
     }
     
 }

9> trim()

忽略字符串的前导空白和尾部空白。

public static void main(String[] args) {
2      
3     String param = "  Hello Kitty  ";
4     System.out.println(param.trim());  //Hello Kitty
5 }

从上面示例可以看出, 调 trim() 方法只是会忽略字符串的前导空白和尾部空白, 对于串中间的空白是不会被处理的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的体育馆管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本体育馆管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此体育馆管理系统利用当下成熟完善的SpringBoot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线选择试题并完成答题,在线查看考核分数。管理员管理收货地址管理、购物车管理、场地管理、场地订单管理、字典管理、赛事管理、赛事收藏管理、赛事评价管理、赛事订单管理、商品管理、商品收藏管理、商品评价管理、商品订单管理、用户管理、管理员管理等功能。体育馆管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:体育馆管理系统;SpringBoot框架;Mysql;自动化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值