JavaSE01_Day02(上中)-StringBuilder修改字符串的API使用、正则表达式、String支持正则表达式的相关API、Object类、包装类

一、StringBuilder修改字符串的API使用

 package cn.tedu.sb;
 /**
  * StringBuilder修改字符串API使用案例
  * @author cjn
* StringBuilder builder = new StringBuilder();
  * 默认无参构造器,内部表示一个空字符串
* StringBuilder builder = new StringBuilder(line);
* 有参构造,内部为将line字符串中的内容复制到builder对象中
  */
 public class StringBuilderAPI {
  public static void main(String[] args) {
  StringBuilder sb = new StringBuilder("好好学习Java");
  //append(String str):字符串拼接,追加在末尾
  sb.append(",就能找到女朋友");
  System.out.println(sb);
  //好 好 学 习 J a v a , 就 能 找 到 女 朋 友
  //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
 
  /*
   * 修改替换replace(int start,int end,String str):含头不含尾
   * 注:在JAVA API中通常使用两个数字表示范围时是"含头不含尾"的。
   * 第一个参数:起始索引位置
   * 第二个参数:结束索引位置
   * 第三个参数:需要进行替换的字符串内容
  */
  sb.replace(9, 16, "挣到高薪");//含头不含尾
  System.out.println(sb);//好好学习Java,挣到高薪
 
  /*
  * 删除delete(int start,int end):含头不含尾
  * 删除“好好学习Java,”
  */
  sb.delete(0, 9);//含头不含尾
  System.out.println(sb);//挣到高薪
 
  /*
   * 指定位置插入字符串内容insert(int offset,String str)
   * 第一个参数:将指定下标的字符进行向后移动
   * 第二个参数:需要进行插入的字符串内容
  */
  sb.insert(0, "懒惰是不可能");//插入位置下标原始的内容向右移
  System.out.println(sb);
 
  /*
  * 字符串反转:reverse()
  */
  sb.reverse();//倒序输出
  System.out.println(sb);
 
  }
 
 }

测试结果:

 好好学习Java,就能找到女朋友
 好好学习Java,挣到高薪
 挣到高薪
 懒惰是不可能挣到高薪
 薪高到挣能可不是惰懒

 

二、正则表达式

2.1 定义:

       正则表达式是一串特定的字符,由这些字符共同组成了一个"特殊的字符串",这个"特殊的字符串"是对于文本规则描述的工具,使用正则表达式可以对于文本格式进行严格的约束。

       正则表达式是用来描述一个字符串的内容格式,使用它通常用来匹配一个字符串的内容是否符合格式要求。

2.2 正则表达式使用的意义:

       在工作过程中经常会需要对字符串进行一些复杂的匹配、查找、替换等相关操作都需要使用正则表达式进行完成。

       可以用于关于用户电话、邮箱等相关验证工作。

2.3正则表达式语法(背下来)

       []:表示一个字符,该字符可以是[]中指定的内容

       例如:

分组():将括号内的内容看做是一个整体

       在描述电话号码时,前面需要有区号,区号的形式可以是0086或者+86,那么此时如果在对一个有区号的电话号进行匹配时,正则表达式的书写需要用到分组(),()这是一个整体,在()中可以使用"|"表示或的关系。

eg: (0086|+86)即可表示的是+86或者是0086

      (abc){3} 表示abc整体出现3次. 可以匹配abcabcabc,不能匹配aaa 或abcabc。

      (abc|def){3}表示abc或def整体出现3次,可以匹配: abcabcabc 或 defdefdef 或 abcdefabc。

"^"和"$"

       在正则表达式的开始可以添加"^",以及在末尾添加"$"表达一个整体,如果不使用,那么正则表达式只匹配某个字符串的部分内容是否符合标准,但是一旦使用了它们,就是要求字符串必须从头到尾都需要满足该匹配规则。

eg:^\w{8,10}$,表示整个字符串只能出现单词字符8~10个

 

三、String支持正则表达式相关API

1.boolean matches(String regex)

案例:编写验证手机号的正则表达式

 package cn.tedu.regex;
 /**
  * 正则表达式匹配手机号格式案例
  * @author cjn
  *
  */
 public class RegexPhoneDemo {
  public static void main(String[] args) {
  /*
  * 匹配手机号是否满足规范要求
  * eg:17090323286
  * 要求:手机号是11位,手机号第一位一定是1,第二位不能是012
  */
  String strPhone = "17090323286";
  /*
  * 正则表达式书写:
  * 1[3456789][0-9]{9}
  * 1[3456789]\d{9}
  * 1[3-9]\d{9}   不建议这种可能存在漏洞
  * 1[0-9&&[^012]]\d{9}
  * 1[\d&&[^012]]\d{9}
  */
  String regex = "1[0-9&&[^012]]\\d{9}";//regex就表示正则表达式
  boolean b = strPhone.matches(regex);
  System.out.println(b);
  }
 }

案例:编写验证邮箱的正则表达式

 package cn.tedu.regex;
 /**
  * 正则表达式匹配邮箱格式案例
  * @author cjn
  *
  */
 public class RegEmailDemo {
  public static void main(String[] args) {
  /*
  * 邮箱规则:
  * eg:2851318853@qq.com 或者2851318853@163.com 或者 baojiaqi0807@gmail.com
  *     guyoupeng@cn.gree.com
  * @符号是必须存在的
  * @符号前面至少有1位,前面的字符可以是字母数字和下划线
  * @符号后面.前面可以是字母数字
  * .后面是字母
  */
  String strEmail = "guyoupeng@cn.gree.com";
  /*
  * 正则表达式:“\.”表示只匹配.
  * [a-zA-Z0-9_]{1,}@[a-zA-z0-9]{1,}(\.[a-zA-Z]{1,}){1,}
  * \w{1,}@[a-zA-z0-9]{1,}(\.[a-zA-Z]{1,}){1,}
  * \w{1,}@[a-zA-z0-9]{1,}(\.[a-zA-Z]+)+
  * \w+@[a-zA-z0-9]+(\.[a-zA-Z]+)+
  */
         //注意此处需要转义,复制后若没有\,需要手动加一个
  String regex = "\\w+@[a-zA-z0-9]+(\\.[a-zA-Z]+)+"
  boolean b = strEmail.matches(regex);
  if (b) {
  System.out.println("是邮箱");
  } else {
  System.out.println("不是邮箱");
  }
  }
 }

扩展:

       假设工作中需要书写一个复杂的正则表达式需要进行匹配验证相关信息内容,往往并不是自己去从头到尾写一个正则表达式,而是通过网上的相关资源查找一个符合当前业务需求的正则表达式进行使用,如果网上没有完全符合业务的正则表达式,可以找一个业务类似的,然后自己稍作修改进行使用。

常用正则表达式查询网址:开源中国 https://tool.oschina.net/regex/#

2.String[] split(String regex)

       该方法需要传递一个正则表达式,然后使用该正则表达式所描述的字符串规则进行匹配对应的字符串内容,如果匹配到符合要求的字符串就将字符串进行拆分。返回的是一个字符串数组对象,数组中的元素就是剩下没有被匹配到的部分。

 package cn.tedu.regex;
 import java.util.Arrays;
 /**
  * String字符串类提供的支持正则的拆分方法案例演示
  * split(String regex)方法
  * @author cjn
  *
  */
 public class SplitDemo {
  public static void main(String[] args) {
  String str = "qwer1234asdf567xyz9";
  /*
  * 准备正则表达式,需求是希望按照数字进行拆分,
  * 拆分以后就会只保留字母部分,将拆分的元素保存到字符串数组中
  * [0-9]{1,}
  * [0-9]+
  * \d{1,}
  * \d+
  */
  String regex = "\\d+";
  String[] strArray = str.split(regex);
  System.out.println(Arrays.toString(strArray));
  System.out.println("拆分出"+strArray.length+"项");
         
         //如果字符串最开始就是拆分项,则会先拆分出一个空字符串
  str = "123qwer1234asdf567xyz9";
         strArray = str.split(regex);
  System.out.println(Arrays.toString(strArray));
  System.out.println("拆分出"+strArray.length+"项");

      //如果字符串最开始就是拆分项,则会先拆分出一个空字符串
         str = ".abc.def.ghi.jkl";
     strArray = str.split("\\.");
     System.out.println(Arrays.toString(strArray));

         //当连续遇到两个拆分项时,中间会拆分出一个空字符串
         str = "abc..def.ghi.jkl";
     strArray = str.split("\\.");
     System.out.println(Arrays.toString(strArray));
 
         //如果是在字符串末尾连续出现拆分项,则所有拆分的空字符串都舍弃
         str = "abc.def.ghi.jkl............................";
         strArray = str.split("\\.");
         System.out.println(Arrays.toString(strArray));    
  }
 }

测试结果:

 [qwer, asdf, xyz]
 拆分出3项
 [, qwer, asdf, xyz]
 拆分出4项
 [, abc, def, ghi, jkl]
 [abc, , def, ghi, jkl]
 [abc, def, ghi, jkl]

3.String replaceAll(String regex,String replacement)

 package cn.tedu.regex;
 /**
  * replaceAll(String regex,String replacement)
   * 将当前字符串中满足正则表达式的部分内容替换为指定的字符串内容
  * @author cjn
  *
  */
 public class ReplaceAllDemo {
  public static void main(String[] args) {
  String str = " Hel lo Wo r ld   ";
  //str = str.replaceAll(" ", "");
  str = str.replaceAll("\\s", "");
  System.out.println("|"+str+"|");
 
  String str1 = "Java教研部的123是苍老师";
  //将字符串中的数字部分替换成"老大",注意替换汉字时要查找对应的Unicode编码才可以,一般都是替换数字或字母
  str1 = str1.replaceAll("[0-9]+", "老大");
  System.out.println(str1);
 
  System.out.println("-----------匹配指定的骂人信息,替换成***------------");
         //上面的----或****有时候两侧或者前后的展现形式不一样,这是工具的问题,但这不影响程序的编写和运行
  String str2 = "nmb是,qnmd。";
  String regex = "(nmb|qnmd)";//()表示组合,|表示或者
  str2 = str2.replaceAll(regex, "***");
  System.out.println(str2);
  }
 }

测试结果:

 |HelloWorld|
 Java教研部的老大是苍老师
 -----------匹配指定的骂人信息,替换成***------------
 ***是,***。

四、Object类

4.1 定义:

       Object类是Java所有类的顶级父类,如果是自定义的一个类,在定义的时候并没有显式的使用extends Object,那么会默认自动继承Object类(隐式使用)。

4.2 存在的意义:

       因为所有的Java类都会有共有的属性及其方法,那么通过”泛化“抽取设计超类,所以在Object类中提供了一些基本的结构内容。

4.3 自定义类需要重写的常用方法:

  • toString()方法

  • euqals()方法

4.4 toString()方法

       由于Object类是所有类的顶级父类,那么在Object类中定义的方法是所有类中都具备的,那么toString方法就是其中之一。之前在学习String字符串类时是可以调用toString()方法,但是调用的toString()方法并不是Object中的toString()方法,而是String类重写的toString()方法。重写的原因是希望在打印字符串对象信息的时候,是一个字符串内容,如果不重写的情况下,会调用Object类中提供的toString()方法,顶级超类中的toString()方法打印的信息格式为:类的全限定名@hashCode。

如果以后在自定义类的情况下,建议都去重写toString(),哪怕以后不用打印对象信息,但是测试时的查看信息还是可以用到的。

4.5 equals()方法

       根据Object中的源码查看,可以看到equals()方法的内容如下:

     public boolean equals(Object obj) {
         return (this == obj);
    }

       该方法返回的是一个boolean值,表示判断比较两个对象的内容地址空间是否是相同的,也就是在比较两个对象的首地址值是否相等。由此可以联想到这个equals()方法和“==”的作用是一致的,那当需要去比较两个对象的内容是否一致的情况下,就需要进行重写equals()方法。

4.6 常见面试题equals和==的区别

       “==”主要用于比较两个引用所指向的内存对象是否是同一个对象,也就意味着是在比较两个引用变量的首地址的值是否一致,如果一致则表示两个引用变量指向的是同一个对象,反之则是不同的对象。

       equals()主要用于比较两个对象中的内容是否一致,也就意味着如果两个引用变量如果指向内容中对象里面的属性值相等时就返回true结果,反之则返回false。由于在Object底层源码中可以得知,仍然是按照地址的方式进行对比,所以无法满足当前要求,那么就需要去重写Object类中的equals()方法。

       eg:两个双胞胎,这两个双胞胎都是独立的个体,是两个对象。如果使用进行比较,比较的结果为false。但是他们“长得一样”,使用equals比较的时候,比较结果为true。所以可以进行总结得出,如果使用“==”就是判断是否为同一个,使用equals是判断像不像。

 public class Demo {
     public static void main(String[] args) {
         Point p = new Point(1,2);
         /*
             Object定义的方法:
             String toString()
             用于将当前对象转换为一个字符串。很少会主动调用这个方法,多用于
             输出对象内容使用。子类不重写时,默认返回的字符串内容是当前对象
             的地址信息,实际开发中作用不大。
          */
         String str = p.toString();//几乎不会主动调用这个方法
         System.out.println(str);
 
         //以下情况对象的toString会被调用:
         //1:输出一个对象到控制台时
         System.out.println(p);//方法内部会调用p.toString将返回的字符串输出到控制台
 
         /*
             2:任何对象和字符串链接结果都是字符串(过程中会将其他对象调
             用toString转换为String后链接)
          */
         String line = "hello!!!" + p;
         System.out.println(line);
 
         /*
             Object定义的方法:
             boolean equals(Object o)
             比较当前对象和参数对象o内容是否相同,相同则返回true否则为false
             Object中该方法的实现内部用"=="比较,因此子类不重写该方法则没有
             实际意义。
          */
         Point p2 = new Point(1,2);
         System.out.println("p2:"+p2);
 
         System.out.println(p==p2);//false
         System.out.println(p.equals(p2));//true(重写后的equals方法)
    }
 }

Person类

 package cn.tedu.object;
 public class Person {
  private String name;//姓名
  private int age;//年龄
  public String getName() {
  return name;
  }
  public void setName(String name) {
  this.name = name;
  }
  public int getAge() {
  return age;
  }
  public void setAge(int age) {
  this.age = age;
  }
  @Override
  public String toString() {
  return "Person [name=" + name + ", age=" + age + "]";
  }
  @Override
  public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + age;
  result = prime * result + ((name == null) ? 0 : name.hashCode());
  return result;
  }
  /**
   * 重写父类的equals方法以后就可以比较两个对象的内容是否一致
  */
  @Override
  public boolean equals(Object obj) {
  //判断两个对象是不是同一个引用
  if (this == obj)
  return true;
  //判断方法参数是否为空
  if (obj == null)
  return false;
  //判断两个对象类型是都一致
  if (getClass() != obj.getClass())
  return false;
  //同一个类型的对象,判断两个对象的属性内容是否一致
  Person other = (Person) obj;
  if (age != other.age)
  return false;
  if (name == null) {
  if (other.name != null)
  return false;
  } else if (!name.equals(other.name))
  return false;
  return true;
  }
 }

Test类

 package cn.tedu.object;
 public class Test {
  public static void main(String[] args) {
  Person p1 = new Person();
  Person p2 = new Person();
  p1.setName("张三");
  p1.setAge(18);
  p2.setName("张三");
  p2.setAge(18);
  System.out.println(p1 == p2);//false
  System.out.println(p1.equals(p2));//true
  }
 }

注意事项:在实际生产中,如果需要给一个类添加set、get、toString、equals方法都会使用工具的如下选项进行生成。

 

五、包装类

5.1 定义:

       包装类就是基本数据类型的对象形式,Java提供了8大基本数据类型,对应也提供了相应的包装类。

注意:包装类都是final类型

  • 数字类型的包装类都继承自java.lang.Number,而char和boolean的包装类直接继承自Object

  • Number是一个抽象类,定义了一些方法,目的是让包装类可以将其表示的基本类型转换为其他数字类型.

5.2 使用包装类意义

       基本数据类型是不能参与引用数据类型数据的计算和使用,所以需要将基本数据类型转换为包装类型进行使用,或者直接定义包装类型的对象。

5.3 基本数据类型和包装类之间的相互转换

       JDK5以前是需要手动进行基本数据类型和包装类之间的相互转换的,在JDK5以后是不需要进行手动转换的,会进行自动转换,这个自动转换的名词叫自动拆装箱功能

手动完成基本数据类型和包装类之间相互转换案例

 package cn.tedu.number;
 /**
  * 基本数据类型和包装类之间相互转换
  * @author cjn
  *
  */
 public class IntegerDemo01 {
  public static void main(String[] args) {
  /*
  * 基本数据类型->包装类
  * 静态方法valueOf()
  */
  int num = 100;
  Integer i1 = Integer.valueOf(num);
 
  /*
   * 包装类->基本数据类型
   * 具体的包装类对象.基本数据类型Value()
   *
  */
  int score = i1.intValue();
  double d = i1.doubleValue();
  byte b = i1.byteValue();
  }
 }

代码不需要执行,只需要记住互相转换的方法即可。

 package integer;
 public class IntegerDemo{
     public static void main(String[] args) {
         //基本类型转换为包装类
         int i = 123;
         //java推荐我们使用包装类的静态方法valueOf将基本类型转换为包装类,而不是直接new
         Integer i1 = Integer.valueOf(i);//注意:Integer会重用-128~127之间的整数对象
         Integer i2 = Integer.valueOf(i);
         System.out.println(i1==i2);//true
         System.out.println(i1.equals(i2));//true
 
         double dou = 123.123;
         Double dou1 = Double.valueOf(dou);//Double则是直接new
         Double dou2 = Double.valueOf(dou);
         System.out.println(dou1==dou2);//false
         System.out.println(dou1.equals(dou2));//true
 
         //包装类转换为基本类型
         int in = i1.intValue();//获取包装类对象中表示的基本类型值
         double doub = i1.doubleValue();
         System.out.println(in);//123
         System.out.println(doub);//123.0
 
         in = dou1.intValue();//大类型转小类型可能存在丢精度!
         doub = dou1.doubleValue();
         System.out.println(in);//123
         System.out.println(doub);//123.123
    }
 }

 

5.4 包装类常用的功能

  • 求数值的最大值和最小值

 package cn.tedu.number;
 /**
  * 包装类常用功能
  * @author cjn
  *
  */
 public class IntegerDemo02 {
  public static void main(String[] args) {
  //通过Integer获取int基本数据类型的最大值和最小值
         //即:通过基本数据类型对应的包装类获取该基本数据类型的最大值和最小值
  int max = Integer.MAX_VALUE;
  System.out.println("int最大值为:"+max);
  int min = Integer.MIN_VALUE;
  System.out.println("int最小值为:"+min);
  //其他的基本数据类型也可以效仿进行获取相关数值
  }
 }
  • 将字符串解析为对应的基本数据类型(应用率较高)

 package cn.tedu.number;
 /**
  * 字符串通过包装类解析为基本数据类型数据
  * @author cjn
  *
  */
 public class IntegerDemo03 {
  public static void main(String[] args) {
  String str = "123456789";
  /*
  * parseInt(String str)
  * 该方法可以将一个字符串内容解析为基本数据类型。
  * 注意事项:被解析的字符串中的内容需要是数字字符串,
  * 不能是带有其他字符的字符串内容,如果带有其他字符内容
  * 那么在进行解析的时候会报相关异常java.lang.NumberFormatException
  */
  int num = Integer.parseInt(str);
  System.out.println(num);
  System.out.println(num + 1);
         
  str = "123.3";//可以转化为double
  //double score = Double.parseDouble(str);
  int score = Integer.parseInt(str);//将double转化为int在此处也不行
  System.out.println(score);
  }
 }

输出结果:

Exception in thread "main" java.lang.NumberFormatException: For input string: "123.3"

字符串中的内容必须要与转换后的基本数据类型严格一致!!!

5.5自动拆装箱(面试题)

       当需要将一个基本数据类型转换为包装类,我们可以调用包装类的静态方法valueOf(),当需要将包装类转换成基本数据类型时,我们可以通过包装类的对象调用xxxValue()方法(虽然包装类的类名不一样,但是调用的方法都是以Value结束的)。JDK5以前是需要手动进行基本数据类型和包装类之间的相互转换的,在JDK5以后是不需要进行手动转换的,会进行自动转换,这个自动转换的名词叫自动拆装箱功能。

       实际上JVM虚拟机是不支持自动拆装箱特性的,自动拆装箱是在编译器编译的过程中进行处理的,只要编译器看到代码中在完成包装类和基本数据类型间的转换时,就会在编译为字节码文件.class的时候进行改变,内部仍是调用相关的API方法实现的包装类和基本数据类型之间的转换工作。

 package cn.tedu.number;
 /**
  * 自动拆装箱案例演示
  * @author cjn
  *
  */
 public class IntegerDemo04 {
  public static void main(String[] args) {
  /*
             触发自动拆箱特性,编译器会补充代码将包装类转换为基本类型,下面的代码会变为:
             int i = new Integer(123).intValue();
          */
         int i = new Integer(123);
         /*
             触发编译器自动装箱特性,代码会被编译器改为:
             Integer in = Integer.valueOf(123);
          */
         Integer in = 123;
         
  Integer i1 = 100;
  int i2 = i1;
  Double d1 = 12.34;
  double d2 = d1;
  Character c1 = 100;
  char c2 = c1;
  Boolean b1 = true;
  boolean b2 = b1;
  }
 }

案例不需要运行

 

posted @ 2021-06-06 22:33  Coder_Cui  阅读(241)  评论(0编辑  收藏  举报