1. 课前回顾:
  2. 1.final
  3. 修饰类:不能被继承
  4. 修饰方法:不能被重写
  5. 修饰局部变量:不能被二次赋值
  6. 修饰对象:地址值不能变,但内容可以变
  7. 修饰成员变量:不能被二次赋值,需要手动赋值
  8. 2.内部类:
  9. 匿名内部类:
  10. new 父类/接口(){
  11. 重写方法
  12. }.重写的方法()
  13. 父类/接口 对象名 = new 父类/接口(){
  14. 重写方法
  15. };
  16. 对象名.重写的方法()
  17. 3.异常:
  18. Throwable
  19. Error
  20. Exception:
  21. 编译时期异常:Exception以及除RuntimeException之外的子类
  22. 运行时期异常:RuntimeException以及子类
  23. 创建异常:
  24. throw new 异常对象
  25. 处理异常:
  26. throws:如果处理多个异常,多个异常之间有子父类继承关系,我们可以直接抛父类
  27. try...catch:
  28. 如果处理多个异常,多个异常之间有子父类继承关系,我们可以直接捕获父类
  29. finally:和try...catch结合使用,表示一定要执行的代码
  30. 多用在关闭资源方面
  31. 自定义异常:
  32. 定义一个类,如果继承Exception,表示编译时期异常;如果继承RuntimeException,表示运行时期异常
  33. 查看异常信息的方法:Throwable
  34. getMessage():获取异常信息
  35. toString():获取异常类型以及信息
  36. printStackTrace():输出的异常信息是最前全的
  37. Object:所有类的根类,所有类都会直接或者间接继承Object
  38. toString()->返回对象的字符串表示形式
  39. 如果想要输出对象名不是地址值的话,就重写toString
  40. equals()->比较对象的地址值
  41. 如果想要比较对象的内容,就重写equals方法
  42. 今日重点:
  43. 1.String的创建以及方法的使用
  44. 2.记住String的一个面试题
  45. 3.会使用StringBuilder去做字符串拼接

第一章.Object类

1.Object的介绍

  1. 1.概述:
  2. 所有类的根类(父类)
  3. 2.注意:
  4. 所有的类都会直接或者间接的去继承Object
  5. 如果一个类没有明确的写出extends 父类,此类的父类就是Object

2.Object类中的toString方法

  1. 1.Object类中的toString方法
  2. public String toString() {
  3. return getClass().getName() + "@" + Integer.toHexString(hashCode());
  4. }
  5. 返回对象的字符串表示形式
  6. 2.总结:
  7. 我们输出对象名,如果没有重写Object类中的toString方法,默认调用的是Object中的toString,直接输出的就是地址值
  8. 如果我们重写了toString方法,那么默认就调用重写后的toString了,如果重写的toString返回还是地址值,重写无意义,所以我们重写toString之后,应该返回属性值
  9. 3.结论:
  10. 如果想输出的对象名不是地址值,就重写Object类中的toString方法
  1. public class Person {
  2. private String name;
  3. private int age;
  4. public Person() {
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Person{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Person person = new Person("柳岩", 36);
  4. System.out.println(person);
  5. System.out.println(person.toString());
  6. ArrayList<String> list = new ArrayList<>();
  7. list.add("孙悟空");
  8. list.add("后裔");
  9. list.add("嫦娥");
  10. System.out.println(list);//[猪八戒,太上老君,玉皇大帝]
  11. System.out.println(list.toString());//[猪八戒,太上老君,玉皇大帝]
  12. }
  13. }

3.Object类中的equals方法

  1. 1.Object类中的equals方法
  2. public boolean equals(Object obj) {
  3. return (this == obj);
  4. }
  5. ==:
  6. 如果是基本类型:比较的是值
  7. 如果是引用类型:比较的是地址值
  8. 2.总结
  9. 如果没有重写equals方法,默认调用Object中的equals方法,比较的是地址值
  10. 如果重写了equals方法,再比较地址值就没有意义了,我们应该重写之后比较对象的内容(属性值)
  1. public class Person {
  2. private String name;
  3. private int age;
  4. public Person() {
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Person{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. /*
  30. 问题1:obj接受的是Person,obj是Object类型,用obj.name和age不行的
  31. 因为name和age是Person的特有成员,多态情况下,调用不了
  32. 解决1:
  33. 将obj向下转型
  34. 问题2:
  35. 如果重写的equals方法接受的不是Person类型,会导致强转异常
  36. 解决2:
  37. 先判断,再向下转型
  38. 问题3:
  39. 如果调用equals方法传递null咋整
  40. 解决3:
  41. 提前做非空判断
  42. 问题4:
  43. 如果调用equals方法传递自己咋整
  44. 解决4:
  45. 提前判断,如果是自己,直接return true
  46. */
  47. /* public boolean equals(Object obj){
  48. if (this==obj){
  49. return true;
  50. }
  51. //非空判断
  52. if (obj==null){
  53. return false;
  54. }
  55. if (obj instanceof Person){
  56. Person person2 = (Person)obj;
  57. return this.name.equals(person2.name) && this.age==person2.age;
  58. }
  59. return false;
  60. }*/
  61. @Override
  62. public boolean equals(Object o) {
  63. if (this == o) return true;
  64. if (o == null || getClass() != o.getClass()) return false;
  65. Person person = (Person) o;
  66. return age == person.age &&
  67. Objects.equals(name, person.name);
  68. }
  69. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Person person1 = new Person("柳岩", 36);
  4. Person person2 = new Person("柳岩", 36);
  5. System.out.println(person1.equals(person2));//false
  6. ArrayList<String> list = new ArrayList<>();
  7. System.out.println(person1.equals(list));
  8. System.out.println(person1.equals(null));
  9. System.out.println(person1.equals(person1));
  10. }
  11. }

小结:

如果想输出对象名不是地址值而是属性值,重写toString

如果想比较两个对象的属性值,重写equals方法

4.Object类中的getClass()方法

  1. Class<?> getClass() -> 获取的是类对象->设计到反射
  1. Person p1 = new Person("柳岩",36);
  2. Class aClass = p1.getClass();
  3. System.out.println(aClass);
  1. 运行结果:class com.atguigu.p_object.Person
  1. 将来学反射,需要记住的单词:
  2. Class
  3. Method 成员方法
  4. Constructor 构造方法
  5. Field 成员变量

day11[基础API和常见算法] - 图1

5.native方法

  1. private static native void registerNatives();
  2. static {
  3. registerNatives();//注册本地方法
  4. }
  5. 方法作用:当该类被加载的时候,调用该方法完成对该类中本地方法的注册
  6. Object类中,除了有registerNatives这个本地方法之外,还有hashCode()、clone()等本地方法,而在Class类中有forName0()这样的本地方法等等。也就是说,凡是包含registerNatives()本地方法的类,同时也包含了其他本地方法。所以,显然,当包含registerNatives()方法的类被加载的时候,注册的方法就是该类所包含的除了registerNatives()方法以外的所有本地方法
  7. registerNatives()注册当前类的本地方法
  8. native:修饰符,关键字-->代表的是本地的
  9. 1.注意:本地方法不是一个抽象方法
  10. 2.本地方法是有方法体的:C语言编写,本地方法的方法体源码没有开源,简单理解为本地方法对Java语言的扩展
  11. 比如后面io流部分,Java本身没有读写功能,调用的都是操作系统的读写功能
  12. 而操作系统上的读写功能用的就是native修饰
  13. windows系统就是C语言写的
  14. 3.位置:本地方法栈
  15. 4.意义:给系统打交道
  1. 小结:
  2. 1.native的方法在本地方法栈中运行
  3. 2.nativeC语言编写,所以我们看不到方法体
  4. 3.registerNatives()代表的是注册当前类中的本地方法
  5. java语言有很多功能没有,很多时候就需要调用c语言编写的本地方法去完成需求
  6. native是独立于jdk之外的,所以我们想使用本地方法之前,需要利用registerNatives()将本地方法注册进来,才能使用

6.GC垃圾回收简介

运行垃圾回收器,JVM将从堆内存中清理对象,清理对象的同时会调用对象的finalize()方法,JVM的垃圾回收器是通过另一个线程开启的,因此程序中的效果并不明显。

  1. public class Person {
  2. @Override
  3. protected void finalize() throws Throwable {
  4. System.out.println(this+"....."+"被回收了!");
  5. }
  6. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. Person person = new Person();
  4. System.out.println(person);
  5. person = null;
  6. System.gc();
  7. }
  8. }
  1. public static void gc()->System类中的方法,运行垃圾回收器
  2. GC:什么时候回收(如果我们的对象没有用)
  3. 比如:Person p = new Person()
  4. p = null;
  5. GC ROOTS-->根据可达性分析算法判断这个对象的引用是否到GC ROOTS中,如果从GC ROOTS
  6. 出发,找不到对应的引用,它会自动判断这个对象该死
  7. 构造方法:创建对象
  8. 析构函数:销毁对象 这是c中有的 java中没有析构函数这个概念
  9. finalize():在回收之前,会自动调用此方法,当然不是垃圾回收器调用的,是本类调用的,是垃圾回收器通知当前类调用的此方法
  1. 垃圾回收关键点:
  2. 1.垃圾回收机制只回收JVM堆内存里的对象空间。
  3. 2.对其他物理连接,比如数据库连接(Connection)、输入流输出流(IO)、Socket连接(网络编程)无能为力
  4. 3.现在的JVM有多种垃圾回收实现算法,表现各异。
  5. 4.垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行
  6. 5.可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。
  7. 6.程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有
  8. 一些效果,但是系统是否进行垃圾回收依然不确定。
  9. 7.垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。
  10. 8.永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

day11[基础API和常见算法] - 图2

第二章.String

1.String介绍

  1. 1.概述:代表的是字符串
  2. 2.特点:
  3. a.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现
  4. 凡是带""的都是String类的一个对象
  5. String s = "abc";
  6. b.字符串是常量,它们的值在创建之后不能更改
  7. String s = "hello";
  8. s+="world";//"helloworld"
  9. c. String 对象是不可变的,所以可以共享
  10. String a = "abc"
  11. String b = "abc";

day11[基础API和常见算法] - 图3

day11[基础API和常见算法] - 图4

2.String的实现原理

  1. 1.实现原理:String底层就是一个数组
  2. 2.jdk8: String底层是一个char[] -> 一个char 内存 2个字节
  3. jdk9: String底层是一个byte[] -> 一个byte 内存 1个字节
  4. 3.注意:
  5. 我们创建的字符串都会自动放到数组中
  6. String s = "abc"-> char[] value = {'a','b','c'}
  1. private final char value[];

数组的前面的修饰符final, 最终的数组,数组一旦建立,数组的地址就被锁死(常量)使用常量的原因,为了线程安全

3.String的创建

  1. String() ->利用空参构造创建String对象
  2. String(String original)->利用有参构造创建String对象
  3. String(char[] value) ->根据char[]数组创建String对象
  4. String(byte[] bytes)->通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String
  5. 简化:
  6. String 变量名 = "" -> 最常用的一种字符串创建方式
  1. public class Demo01String {
  2. public static void main(String[] args) {
  3. //String() ->利用空参构造创建String对象
  4. String s1 = new String();
  5. System.out.println(s1);
  6. //String(String original)->利用有参构造创建String对象
  7. String s2 = new String("abc");
  8. System.out.println(s2);
  9. //String(char[] value) ->根据char[]数组创建String对象
  10. char[] chars = {'a','b','c'};
  11. String s3 = new String(chars);
  12. System.out.println(s3);
  13. /*
  14. String(byte[] bytes)->通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
  15. 平台:指的是操作系统 操作系统默认编码集为GBK
  16. IDEA:运行的时候添加了一个启动参数,而启动参数将idea运行时遵循的编码设置成了utf-8
  17. 在utf-8编码中 3个字节代表一个中文
  18. 在GBK中 2个字节代表一个中文
  19. */
  20. byte[] bytes = {-28, -67, -96};
  21. String s4 = new String(bytes);
  22. System.out.println(s4);
  23. }
  24. }

day11[基础API和常见算法] - 图5

  1. 扩展构造:
  2. String(byte[] bytes, String charsetName) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。,可以根据我们指定的字符集去创建String对象
  3. String(byte[] bytes, int offset, int length) :将byte数组的一部分转成String
  4. bytes:要转的数组
  5. offset:从数组的哪个索引开始转
  6. length:转多少个
  7. String(char[] value, int offset, int count) :将char数组的一部分转成String
  8. value:要转的数组
  9. offset:从数组的哪个索引开始转
  10. count:转多少个
  1. public class Demo02String {
  2. public static void main(String[] args) throws UnsupportedEncodingException {
  3. /*
  4. String(byte[] bytes, String charsetName) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
  5. 可以根据我们指定的字符集去创建String对象
  6. */
  7. byte[] bytes = {-28, -67, -96,-27, -91, -67};
  8. String s1 = new String(bytes,"GBK");
  9. System.out.println(s1);
  10. /*
  11. String(byte[] bytes, int offset, int length) :将byte数组的一部分转成String
  12. bytes:要转的数组
  13. offset:从数组的哪个索引开始转
  14. length:转多少个
  15. */
  16. byte[] bytes1 = {97,98,99,100};
  17. String s2 = new String(bytes1,0,2);
  18. System.out.println(s2);//ab
  19. /*
  20. String(char[] value, int offset, int count) :将char数组的一部分转成String
  21. value:要转的数组
  22. offset:从数组的哪个索引开始转
  23. count:转多少个
  24. */
  25. char[] chars = {'a','b','c','d'};
  26. String s3 = new String(chars,1,3);
  27. System.out.println(s3);//bcd
  28. }
  29. }

4.String 面试题

  1. public class Test04 {
  2. public static void main(String[] args) {
  3. String s1 = "abc";
  4. String s2 = "abc";
  5. String s3 = new String("abc");
  6. System.out.println(s1==s2);//true
  7. System.out.println(s2==s3);//false
  8. }
  9. }

day11[基础API和常见算法] - 图6

  1. String s = new String("abc"), 创建了几个对象?
  2. 1个或者2
  3. 1个: 如果"abc"提前创建出来了,那么String s = new String("abc")就创建了一个
  4. 2个: 如果"abc"没有提前创建出来,那么String s = new String("abc"),就创建了两个
  5. 首先自己会先将"abc"创建出来,其次new

day11[基础API和常见算法] - 图7

5.字符串常见问题

  1. public class Test05 {
  2. public static void main(String[] args) {
  3. String s1 = "hello";
  4. String s2 = "world";
  5. String s3 = "helloworld";
  6. String s4 = "hello"+"world";
  7. String s5 = s1+"world";
  8. String s6 = s1+s2;
  9. System.out.println(s3==s4);//true
  10. System.out.println(s3==s5);//false
  11. System.out.println(s4==s5);//false
  12. System.out.println(s3==s6);//false
  13. }
  14. }

如果定义字符串等号右边是字符串字面值,都是在常量池中

如果定义字符串等号右边有变量参与,会在堆内存中创建新的对象,开辟新的空间

以上代码反编译结果:

day11[基础API和常见算法] - 图8

第三章.String的方法

1.判断方法

  1. - public boolean equals (Object anObject) :比较字符串内容(双引号里面的)是否相等
  2. - public boolean equalsIgnoreCase (String anotherString) :比较字符串内容(双引号里面的)是否相等,忽略大小写
  1. public class Demo01Equals {
  2. public static void main(String[] args) {
  3. String s1 = "abc";
  4. String s2 = new String("abc");
  5. //- public boolean equals (Object anObject) :比较字符串内容(双引号里面的)是否相等
  6. boolean equals = s1.equals(s2);
  7. System.out.println(equals);
  8. //- public boolean equalsIgnoreCase (String anotherString) :比较字符串内容(双引号里面的)是否相等,忽略大小写
  9. String s3 = new String("ABC");
  10. System.out.println(s3.equals(s1));
  11. System.out.println(s3.equalsIgnoreCase(s1));
  12. }
  13. }

2.练习1

  1. 已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
  2. 步骤:
  3. 1.定义两个已知的字符串 分别代表username password
  4. 2.创建Scanner对象
  5. 3.循环输入,如果输入的用户名和密码跟已知的username password相等,证明登录成功
  6. 4.否则,登录失败
  1. public class Demo02EqualsTest {
  2. public static void main(String[] args) {
  3. //定义已知的用户名和密码
  4. String username = "root";
  5. String password = "1234";
  6. //创建Scanner对象
  7. Scanner sc = new Scanner(System.in);
  8. for (int i = 0; i < 3; i++) {
  9. System.out.println("请您输入要登录的用户名:");
  10. String name = sc.next();
  11. System.out.println("请您输入要登录的密码:");
  12. String pwd = sc.next();
  13. if (name.equals(username)&&pwd.equals(password)){
  14. System.out.println("登录成功");
  15. }else{
  16. if (i==2){
  17. System.out.println("账号冻结");
  18. }else{
  19. System.out.println("登录失败");
  20. }
  21. }
  22. }
  23. }
  24. }

在开发中,如何正确判断String的内容呢?

  1. public class Demo03Equals {
  2. public static void main(String[] args) {
  3. String s = null;
  4. method(s);
  5. }
  6. private static void method(String s) {
  7. /*
  8. 如果将s放在前面调用equals方法,由于s是一个变量,将来s接收的值不一定是啥
  9. 如果s接收的是null就会出现空指针
  10. 所以我们可以将固定的字符串放在前面调用equals方法,防止空指针
  11. */
  12. /*if (s.equals("abc")){
  13. System.out.println("s的内容是abc");
  14. }*/
  15. if ("abc".equals(s)){
  16. System.out.println("s的内容是abc");
  17. }
  18. }
  19. }

3.获取功能

  1. - public int length () :返回此字符串的长度。
  2. - public String concat (String str) :将指定的字符串连接到该字符串的末尾。
  3. - public char charAt (int index) :返回指定索引处的 char值。
  4. - public int indexOf (String str) :获取的是指定字符串在老串中第一次出现的索引位置
  5. - public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
  6. - public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndexendIndex截取字符串。含beginIndex,不含endIndex
  1. public class Demo04Get {
  2. public static void main(String[] args) {
  3. String s = "abcdef";
  4. //- public int length () :返回此字符串的长度。
  5. System.out.println(s.length());
  6. //- public String concat (String str) :将指定的字符串连接到该字符串的末尾。,返回一个新串
  7. String s1 = s.concat("hahah");
  8. System.out.println(s1);
  9. System.out.println(s);
  10. //- public char charAt (int index) :返回指定索引处的 char值。
  11. char s2 = s.charAt(2);
  12. System.out.println(s2);
  13. //- public int indexOf (String str) :获取的是指定字符串在老串中第一次出现的索引位置
  14. int index = s.indexOf("a");
  15. System.out.println(index);
  16. //- public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
  17. String substring = s.substring(2);
  18. System.out.println(substring);
  19. /*- public String substring (int beginIndex, int endIndex) :
  20. 返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。*/
  21. String substring1 = s.substring(2, 4);
  22. System.out.println(substring1);
  23. }
  24. }

4.练习2

  1. 遍历字符串
  1. public class Demo05GetTest {
  2. public static void main(String[] args) {
  3. String s = "abcdef";
  4. for (int i = 0; i < s.length(); i++) {
  5. char c = s.charAt(i);
  6. System.out.println(c);
  7. }
  8. System.out.println("==============");
  9. char[] chars = s.toCharArray();
  10. for (int i = 0; i < chars.length; i++) {
  11. System.out.println(chars[i]);
  12. }
  13. }
  14. }

5.练习3

  1. 在控制台输出结果。例如,数组为 int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
  1. public class Demo06GetTest {
  2. public static void main(String[] args) {
  3. int[] arr = {1, 2, 3};
  4. String str = "[";
  5. for (int i = 0; i < arr.length; i++) {
  6. if (i==arr.length-1){
  7. str = str+arr[i]+"]";
  8. }else{
  9. str = str+arr[i]+",";
  10. }
  11. }
  12. System.out.println(str);
  13. }
  14. }

6.转换功能

  1. - public char[] toCharArray () :将此字符串转换为新的字符数组。
  2. - public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
  3. - public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使用replacement字符串替换。
  1. public class Demo07ZhuanHuan {
  2. public static void main(String[] args) {
  3. String s = "abc";
  4. //- public char[] toCharArray () :将此字符串转换为新的字符数组。
  5. char[] chars = s.toCharArray();
  6. for (int i = 0; i < chars.length; i++) {
  7. System.out.println(chars[i]);
  8. }
  9. //- public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
  10. byte[] bytes = s.getBytes();
  11. System.out.println(Arrays.toString(bytes));
  12. /*- public String replace (CharSequence target, CharSequence replacement) :
  13. 将与target匹配的字符串使用replacement字符串替换。*/
  14. String s1 = s.replace("a", "z");
  15. System.out.println(s1);
  16. }
  17. }

7.练习4

  1. 键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
  2. 步骤:
  3. 1.创建Scanner对象,调用next方法录入一个字符串 abbcAA
  4. 2.定义三个变量,分别统计大写,小写,数字字符的个数
  5. int big = 0;
  6. int small = 0;
  7. int number = 0;
  8. 3.遍历字符串,将每一个字符获取出来
  9. 如何判断大写字母? B 66 A-Z->整数范围是:65-90 如果字符对应的int值在65-90之间,证明是大写字母
  10. big++
  11. 如何判断小写字母? a-z->整数范围是:97-122 如果字符对应的int值在97-122之间,证明是小写字母
  12. small++
  13. 如何判断数字? '0'-'9'->整数范围是:48-57 如果字符对应的int值在48-57之间,证明是数字
  14. number++
  1. public class Demo08ZhuanHuanTest {
  2. public static void main(String[] args) {
  3. Scanner sc = new Scanner(System.in);
  4. //统计大写字母个数
  5. int big = 0;
  6. //统计小写字母个数
  7. int small = 0;
  8. //统计数字个数
  9. int number = 0;
  10. System.out.println("请你输入一个字符串:");
  11. String data = sc.next();
  12. //遍历字符串
  13. char[] chars = data.toCharArray();
  14. for (int i = 0; i < chars.length; i++) {
  15. char c = chars[i];
  16. if (c>='A' && c<='Z'){
  17. big++;
  18. }
  19. if (c>='a' && c <='z'){
  20. small++;
  21. }
  22. if (c>='0' && c<='9'){
  23. number++;
  24. }
  25. }
  26. System.out.println("大写字母个数为:"+big);
  27. System.out.println("小写字母个数为:"+small);
  28. System.out.println("数字个数为:"+number);
  29. }
  30. }

8.分割功能

  1. public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。
  1. public class Demo09Split {
  2. public static void main(String[] args) {
  3. String s = "abc,txt";
  4. String[] split = s.split(",");
  5. System.out.println(Arrays.toString(split));
  6. String s1 = "abc.txt";
  7. String[] split1 = s1.split("\\.");
  8. System.out.println(Arrays.toString(split1));
  9. }
  10. }

第四章.扩展方法

  1. boolean contains(CharSequence s) :判断老串中是否包含指定的串儿
  2. boolean endsWith(String suffix) :判断字符串是否以指定的串儿结尾
  3. boolean startsWith(String prefix) :判断字符串是否以指定的串儿开头
  4. String toLowerCase() :将字符串转成小写
  5. String toUpperCase() :将字符串转成大写
  6. String trim() :去掉字符串两端空格
  1. public class Demo10Other {
  2. public static void main(String[] args) {
  3. String s = "abcdefg";
  4. //boolean contains(CharSequence s) :判断老串中是否包含指定的串儿
  5. System.out.println(s.contains("a"));
  6. //boolean endsWith(String suffix) :判断字符串是否以指定的串儿结尾
  7. System.out.println(s.endsWith("fg"));
  8. //boolean startsWith(String prefix) :判断字符串是否以指定的串儿开头
  9. System.out.println(s.startsWith("abc"));
  10. //String toLowerCase() :将字符串转成小写
  11. String s1 = "ABCDEFG";
  12. System.out.println(s1.toLowerCase());
  13. //String toUpperCase() :将字符串转成大写
  14. System.out.println(s.toUpperCase());
  15. String s2 = "ABC1212abc";
  16. System.out.println(s2.toUpperCase());
  17. //String trim() :去掉字符串两端空格
  18. System.out.println("========================");
  19. String s3 = " abc d e ";
  20. System.out.println(s3);
  21. String trim = s3.trim();
  22. System.out.println(trim);
  23. System.out.println("=============去掉所有空格=============");
  24. String replace = s3.replace(" ", "");
  25. System.out.println(replace);
  26. }
  27. }

第五章.StringBuilder

1.StringBuilder的介绍

  1. 1.为什么学:如果要是用String做字符串拼接,每拼接一次,都会产生一个新的串儿,就会在堆内存中产生一个新的空间
  2. 耗费内存,所以出现了StringBuilder来代替String做字符串拼接
  3. 2.概述:
  4. 一个可变的字符序列
  5. 3.特点:
  6. a.StringBuilder底层是一个char[] value;没有被final修饰
  7. b.StringBuilder创建出来自带一个缓冲区(char[]),默认长度为16
  8. c.如果拼接字符串,所有的字符串都会在这个缓冲区保存,不会在堆内存中产生新的串儿,始终就这一个StringBuilder对象,不会产生新的对象
  9. d.如果超过了16,StringBuilder中的缓冲区(char[])自动扩容
  10. 注意:扩容并不是直接改变底层数组的长度,而是采用了(Arrays.copyOf->数组复制)
  11. e.扩容多少: 2倍+2

day11[基础API和常见算法] - 图9

2.StringBuilder的使用

  1. 1.构造:
  2. StringBuilder()->创建一个StringBuilder对象 缓冲区是空的
  3. StringBuilder(String str)->创建一个StringBuilder对象 缓冲区存好了str
  1. public class Test01StringBuilder {
  2. public static void main(String[] args) {
  3. StringBuilder sb = new StringBuilder();
  4. System.out.println(sb);
  5. StringBuilder sb1 = new StringBuilder("abc");
  6. System.out.println(sb1);
  7. }
  8. }
  1. StringBuilder的方法:
  2. StringBuilder append(任意类型数据)->数据拼接,返回的是StringBuilder自己
  3. StringBuilder reverse() -> 字符串翻转->返回的StringBuilder,也是自己
  4. String toString()->将StringBuilder转成String对象
  1. public class Test02StringBuilder {
  2. public static void main(String[] args) {
  3. StringBuilder sb = new StringBuilder();
  4. StringBuilder sb1 = sb.append("哈哈哈");
  5. System.out.println(sb);
  6. //链式调用
  7. sb.append(1).append("孙悟空").append("唐僧");
  8. System.out.println(sb);
  9. System.out.println("=======================");
  10. sb.reverse();
  11. System.out.println(sb);
  12. System.out.println("=======================");
  13. //String toString()->将StringBuilder转成String对象
  14. String s = sb.toString();
  15. System.out.println(s.length());
  16. }
  17. }
  1. //判断字符串是否对称
  2. public class Test03StringBuilder {
  3. public static void main(String[] args) {
  4. String s = "蝶恋花香花恋蝶";
  5. StringBuilder sb = new StringBuilder(s);
  6. sb.reverse();
  7. String s1 = sb.toString();
  8. if (s.equals(s1)){
  9. System.out.println("对称");
  10. }
  11. }
  12. }

3.练习

  1. 定义一个方法,按照指定格式打印数组元素。例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
  1. public class Test04StringBuilder {
  2. public static void main(String[] args) {
  3. StringBuilder sb = new StringBuilder("[");
  4. int[] arr = {1,2,3,4};
  5. for (int i = 0; i < arr.length; i++) {
  6. if (i==arr.length-1){
  7. sb.append(arr[i]).append("]");
  8. }else{
  9. sb.append(arr[i]).append(", ");
  10. }
  11. }
  12. System.out.println(sb.toString());
  13. }
  14. }

4.String 和StringBuilder以及StringBuffer区别

  1. String:
  2. 效率低
  1. StringBuilderStringBuffer区别
  2. StringBuilder:
  3. 线程不安全,线程不同步
  4. 效率高
  5. StringBuffer:
  6. 线程安全
  7. 效率比StringBuilder
  8. 从拼接效率上来看,三者排序(由快到慢)
  9. StringBuilder>StringBuffer>String