《第一阶段 语言基础 面向对象 Day07笔记》————————第七讲 面向对象

课程大纲

课程内容

学习效果

掌握目标

面向对象

Static关键字

掌握

熟练掌握static的含义和用法

String类

掌握

熟练掌握String类型的原理和使用方式

字符串缓冲区StringBuilder

掌握

熟练掌握StringBuilder的原理和使用方式

 

一、static关键字

1、问题引入

如果某个类型的所有对象,都具有一个相同的属性值,那么这个属性值就没有必要在所有对象中,都存储一份。坏处:浪费内存空间;维护难度大,一旦需要修改,就得修改所有的对象。如何解决这个问题呢?

当在定义类的时候,类中都会有相应的属性和方法。而属性和方法都是通过创建本类对象调用的。当在调用对象的某个方法时,这个方法没有访问对象的特有数据(属性——成员变量)时,创建这个对象有些多余。可是不创建对象,方法又调用不了,这时就会想,那么我们能不能不创建对象,就可以调用方法呢?

不使用static关键字

示例代码

public class Student {

 

private int id;

private String name;

private int age;

private String country="中国";

 

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

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;

}

}

内存图景

2、static关键字概述(静态)

static关键字可以用于修饰类的成员变量、方法和代码块。

static修饰的变量称为静态变量。

static修饰的方法称为静态方法。

static修饰的初始化代码块,称为静态初始化块。

static修饰类,静态内部类(后面讲)

3、静态变量

用static修饰的变量叫做静态变量(类变量)。

静态变量的特征:类的所有对象共享同一个静态变量。

例如:static int x

案例:修改上面例子,把国家修改成静态变量

public class Student {

private int id;

private String name;

private int age;

static String country="中国";  // 静态变量

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

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;

}

public void sayHello(){

System.out.println("hello...");

}

public int add(in

内存图景

(1)静态变量的特点

静态的解释:static关键字

静态、静止的。静态变量不会随着对象的变化而变化。

加载时机:

随着类的加载而加载。

静态变量随着类的加载进方法区,就直接在静态区给开辟了存储静态变量的内存空间。

静态变量优先于对象而存在。

静态变量被所有该类对象所共享。

代码层面:

可以使用类名直接调用,不需要使用对象名称。在不创建对象的前提下,仍然可以使用这个静态变量。建议使用类名来访问。

(2)静态变量和非静态变量的区别

  1. 概念上,所属不同:

  非静态变量属于对象。

  静态变量属于类,类变量。

  1. 内存空间不同,存储位置不同

  非静态变量属于对象,所以存储在堆内存中。

静态变量属于类,存储在方法区的静态区中。

  1. 内存时间不同,生命周期不同

  非静态变量属于对象,所以生命周期和对象相同,随着对象的创建而存在,随着对象的消失而消失。

静态变量属于类,所以生命周期和类相同,随着类的加载(创建对象、类名访问静态变量、类名访问静态方法、反射的方式、加载子类、运行某个测试类)而存在,随着类的消失(内存管理)而消失。

  1. 访问方式不同

  非静态变量只能使用对象名访问。

  静态变量既可以使用对象访问,也可以通过类名访问:

    类名.静态变量名

    类名.静态方法名()

4、静态方法

当static 修饰成员方法时,该方法称为类方法或静态方法。静态方法在声明中有static ,建议使用类名来直接调用,而不需要创建类的对象。调用方式非常简单。

(1)语法格式

格式:

修饰符 static 返回值类型 方法名 (参数列表){

// 执行语句

}

举例:在Student类中定义静态方法

public static void showNum() {

System.out.println("num:" + autoIncrementNum);

}

(2)静态方法调用的注意事项

静态方法可以直接访问静态变量和静态方法。(静态可以访问静态)

静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。(静态不能访问非静态)

静态方法中,不能使用this关键字

静态方法只能访问静态成员。(静态可以访问静态)(静态不能访问非静态)

示例代码

public class Student {

private int id;

private String name;

private int age;

static String country="中国";  // 静态变量

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

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;

}

public static void sayHello(){

System.out.println("hello..."+country);  //静态方法中可以直接访问静态成员

//System.out.println(name);静态方法中,不能方法非静态成员(成员变量和成员方法)

//add(1,2);

}

public void introduce(){

System.out.println("我是"+name+" 来自"+country);  // 非静态方法中可以直接方法静态成员

}

public int add(int a,int b){

return a+b;

}

}

(3)调用格式

被static修饰的成员可以并且建议通过类名直接访问。虽然也可以通过对象名访问静态成员,原因即多个对象均属于一个类,共享使用同一个静态成员,但是不建议,会出现警告信息。

格式

// 访问类变量

类名.类变量名;

// 调用静态方法

类名.静态方法名(参数)

示例代码

public static void main(String[] args) {

Student stu1 = new Student();

Student stu2 = new Student();

/*

System.out.println(stu1.country);

System.out.println(stu2.country);

*/

    //System.out.println(Student.country);  // 静态变量 是不属于任何一个对象的,直接属于类

stu1.sayHello();

stu2.sayHello();

stu1.add(1,2);

Student.sayHello();  //静态方法可以通过类名直接调用

//Student.add(1,2);  不能通过类名直接调用成员方法(非静态方法)   

}

5、静态初始化块

static 修饰的初始化块

特征:在类加载时,只会执行一次

例如: static{}

示例代码

{  // 初始化代码块——每创建一个对象,就会执行一次

System.out.println("初始化代码块");

}

 

static{  // 静态代码块——在类加载时,只会执行一次

System.out.println("静态初始化代码块");

}

6、案例

案例1:使用static 完成 投票功能。

最多有5个人投票,定义投票人的类(voter),

在这个类中定义一个投票的方法,当票数超过5时,提示不能再投票。

public class Voter {

  private static int num;  //静态变量,所有对象共享

  public void vote(){

  if(num>=5){

  System.out.println("票数已满");

  }else{

  num++;

  System.out.println("已投"+num+"票");

  }

  }

}

 

案例2:使用计数器num统计创建User对象的个数(提示构造方法里对num进行自加操作)

public class User {

private static int num;  //计数——static的,所有对象共享

public User(){

num++;

System.out.println("已创建"+num+"个对象");

}

}

案例3: 定义一个int类型数组操作的工具类,MyArrays。方法包括:

         最大值,最小值,升序排列,求和方法

public class MyArrays{  // 作业

 

/*

 *  定义一个int类型数组操作的工具类,MyArrays。方法包括:

                       最大值,最小值,升序排列,求和方法

 * */

 

//获取最大值

public static int getMax(int[] aa){

int max = aa[0];  //假设

for(int i=0;i<aa.length;i++){

if(aa[i]>max){

max = aa[i];

}

}

return max;

}

//获取最小值

public static int getMin(int[] aa){

int min = aa[0];  //假设

for(int i=0;i<aa.length;i++){

if(aa[i]<min){

min = aa[i];

}

}

return min;

}

//排序

public static void sort(int[] aa){

for(int i=0;i<aa.length;i++){

for(int j=0;j<aa.length-1-i;j++){

if(aa[j]>aa[j+1]){

 

int temp = 0;

temp = aa[j];

aa[j] = aa[j+1];

aa[j+1]=temp;

 

}

}

}

}

//求和

public static int getSum(int[] aa){

int sum = 0;

//增强型for循环(foreach循环)

for(int x:aa){

sum = sum+x;

}

return sum;

}

}

7、static特征总结

1 静态方法中不能访问非静态成员变量和成员方法(非静态方法可以方法静态变量)  -非静态方法可以访问静态成员变量和静态方法

2 静态方法中不能使用this关键字

3 随着类的加载而加载,静态会随着类的加载而加载,随着类的消失而消失。说明它的生命周期很长。

4 优先于对象存在。-->静态是先存在,对象是后存在。

5 被所有实例(对象)所共享。

6 可以直接被类名调用

静态变量(类变量)和实例变量的区别:

    存放位置

        1:类变量随着类的加载而加载存在于方法区中.

        2:实例变量随着对象的建立而存在于堆内存中.

    生命周期

        1:类变量生命周期最长,随着类的消失而消失.

        2:实例变量生命周期随着对象的消失而消失.

静态优缺点

1:优点:对对象的共享数据进行单独空间的存储,节省空间

2:缺点:生命周期过长

访问出现局限性。(静态只能访问静态)

什么时候定义静态变量

    1:静态变量(类变量)当对象中出现共享数据

  例如:学生的学校名称。学校名称可以共享

        对象的数据要定义为非静态的存放在对内存中(学生的姓名,学生的年龄)

什么时候定义静态方法

        如果功能内部没有访问到非静态数据(对象的特有数据。那么该功能就可以定义为静态)

8、单例模式(Singleton)

GOF的23种设计模式中的一种。

一些人总结出来用来解决特定问题的固定的解决方案。

解决一个类在内存中只能存在一个对象,想要保证对象的唯一。

1 为了避免其他程序过多的建立该类对象。禁止其他程序建立该类对象。

2 为了其他程序可以访问该类对象,在本类中自定义一个对象。

3 方便其他程序对自定义类的对象的访问,对外提供一些访问方式。

方式:

1将构造方法私有化。

2在类中创建一个私有的本类对象。

3提供一个用类名调用的公有方法获取该对象。

示例代码

class Single {

private static Single s = new Single(); // 饿汉式

private Single() {

}

public static Single getInstance() {

return s;

}

}

class Single2 {

private static Single2 s = null; // 懒汉式

private Single2() {

}

public static Single2 getInstance() {

if (s == null) {

s = new Single2();

}

return s;

}

}

二、String类

1、概述

  1. String就是字符串类型,属于java.lang包,不需要导包。
  2. 所有的字符串常量(“Hello World”、”abc”)都属于String类型的对象。
  3. 字符串字面值属于常量,存储在方法区的常量池中。
  4. String类型在创建之后就无法更改(是一个不可变的字符序列)。
  5. 不可变的原因是String类型只提供了构造方法,没有提供set方法,因此只能在创建对象的时候,初始化成员变量,将来对象创建完成之后,无法通过方法来修改。

public static void main(String[] args) {

String str1 = "abc";

System.out.println(str1);

str1 = "xyz";

System.out.println(str1);

// 不可变? 可变?——str1是引用,是内存地址。这里指的不可变是字符串(在内存中的字符串内容不会改变)

}

2、常量池

   任何好的编程语言的关键目标之一是高效的使用内存。随着应用程序的增长,String字面值占用大量的内存非常常见。对程序而言,全部String字面值中往往有大量的冗余,为了使Java更高效地使用内存,JVM留出一块特殊的内存区域,称为“String常量池”。当编译器遇到String字面值时,它检查该池内是否已经存在相同的String字面值。如果找到,则将新的字面值的引用指向现有的String,而不创建任何新的String字面值对象。

3、String类常见的构造方法

  1. String():创建一个空字符串

2、String(String original):创建参数字符串的一个副本(参数字符串是在常量池中,构造方法创建的字符串是在堆内存中)。

3、String(byte[] arr):将一个字节数组转成一个字符串。

将我们不认识的字节数组,转成了我们认识的字符串,过程叫做【解码】。

查询的是当前平台默认的编码表。

4、String(byte[] arr, int offset, int length):将字节数组的一部分转成字符串

5、String(char[] arr):将字符数组转成字符串。

既不是编码,也不是解码,只不过是把字符数组转成了字符串

  1. String(char[] arr, int offset, int length):将字符数组的一部分转成字符串。

示例代码

public static void main(String[] args) {

/*

String str = new String();   // 创建了一个空串  ""

//String str = "";

System.out.println(str);

 

String str2 = new String("abc");

//String str2 = "abc";

System.out.println(str2);

*/

String str1 = "abc";  // 内存中有几个对象???  一个——常量池中

String str2 = "abc";  // 内存中有几个对象??? 一个

String str3 = new String("abc");  //两个,一个在堆区,一个在常量池

System.out.println(str1==str2);  //true

System.out.println(str1==str3);  //false

}

 

public static void main(String[] args) {

//byte[] b = new byte[]{};

String str = new String(new byte[]{65,66,67,68,69});

System.out.println(str);

String str2 = new String(new byte[]{65,66,67,68,69},2,3);//从第几个元素开始,取几个

System.out.println(str2);

String str3 = new String(new char[]{'a','b','c','d','e'});

System.out.println(str3);

String str4 = new String(new char[]{'a','b','c','d','e'},2,3);

System.out.println(str4);

}

 

4、内存图

5、String类的方法介绍

(1)API

概述

API(Application Programming Interface),应用程序编程接口。

Java API是一本程序员的字典 ,是JDK中提供给我们使用的类的说明文档。这些类将底层的代码实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。所以我们可以通过查询API的方式,来学习Java提供的类,并得知如何使用它们。

使用步骤

1.打开帮助文档。

2.点击显示,找到索引,看到输入框。

3.你要找谁?在输入框里输入,然后回车。

4.看包。java.lang下的类不需要导包,其他需要。

5.看类的解释和说明。

6.学习构造方法。

7.使用成员方法。

演示

使用API文档查看之前使用过的Scanner类和Random类

(2)判断功能的方法

  1. equals(Object obj):判断调用者和参数对象描述的字符串内容是否相同
  2. equalsIgnoreCase(String otherStr):忽略大小写判断两个字符串内容是否相同
  3. contains(String str):判断调用者是否包含了str这个子串
  4. startsWith(String prefix):判断调用者是否以prefix开头
  5. endsWith(String suffix):判断调用者是否以suffix结尾
  6. isEmpty():判断调用者是否是空串

 

示例代码

String s1 = "aaa";

String s2 = new String("aaa");

System.out.println(s1.equals(s2));

 

//判断键盘输入的值是否为admin

Scanner sc = new Scanner(System.in);

String str = sc.nextLine();

 

 

System.out.println(str=="admin");

System.out.println("admin".equals(str));  //常量和变量使用equals比较内容时,尽量把常量写在前面

 

//equalsIgnoreCase 忽略大小写的比较

String str1 = "aaa";

String str2 = "AAA";

System.out.println(str1.equals(str2));

System.out.println(str1.equalsIgnoreCase(str2));

 

//contains 判断字符串是否包含某内容(子串)

String str = "abcde";

System.out.println(str.contains("ab"));

System.out.println(str.contains("cde"));

System.out.println(str.contains("ac"));

 

// startsWith   endsWith  判断字符串是否以某个值开头,是否以某个值结尾

String str="http://www.sina.com.cn";

 

System.out.println(str.startsWith("h"));

System.out.println(str.startsWith("http"));

System.out.println(str.startsWith("http://www.sina.com.cn"));

System.out.println(str.startsWith("a"));

 

 

System.out.println(str.endsWith("cn"));

System.out.println(str.endsWith(".cn"));

 

 

 

// isEmpty 判断字符串是否 为空串

String str1 = "";

String str2 = new String();

String str3 = new String("");

String str4 = " ";

 

System.out.println(str1.isEmpty());

System.out.println(str2.isEmpty());

System.out.println(str3.isEmpty());

System.out.println(str4.isEmpty());

 

(3)获取功能的方法

  1. length():获取字符串字符的个数
  2. charAt(int index):返回调用者字符串中索引为index的字符(和length方法结合之后可以遍历字符串)
  3. substring(int beginIndex):获取一个字符串,内容是从当前字符串的beginIndex索引开始
  4. substring(int beginIndex, int endIndex):获取一个指定索引范围的子串

注意事项:1、包含头不包含尾,返回的结果中,不包含endIndex索引指向的字符;2、所有的方法都无法修改字符串对象本身,一般都是返回一个新的字符串对象

  1. indexOf家族:

  indexOf(int ch):返回ch字符在当前调用者字符串中,第一次出现的索引

indexOf(int ch, int fromIndex):从fromIndex索引开始寻找,找到ch字符在当前字符串中第一次出现的索引

indexOf(String str):返回的是str这个字符串在调用者字符串中第一次出现的索引

indexOf(String str, int fromIndex):从fromIndex索引开始寻找,找到str字符串在当前字符串中第一次出现的索引(注意:无论从哪个位置开始找,所有字符的索引都不会变化)

6、lastIndexOf家族:

和IndexOf基本一样,只不过是从后往前找,所有字符和字符串的索引也都不会发生变化

示例代码

public class Demo05_String类的常用方法_获取功能的方法 {

public static void main(String[] args) {

/*

// 1 length()  获取字符串长度(由多少个字符组成)

String str = "abc";

int x = str.length();

System.out.println(x);

*/

 

/*

//2 charAt 获取某个位置上的字符

String str = "abcde";

char c = str.charAt(1);

System.out.println(c);

*/

/*

//3 substring 截取子串

String str = "abcdefg";

String result = str.substring(2);  //取到最后

System.out.println(result);

String result2 = str.substring(2,4); // 左闭右开

System.out.println(result2);

 

*/

/*

//4 indexOf 查找位置

String str = "abcdeabcd";

int idx = str.indexOf("cd");

System.out.println(idx);

 

int idx2 = str.indexOf("ab",3);

//int idx2 = str.indexOf("ab",-3);// 第2个参数为负数,相当于0

System.out.println(idx2);

 

int idx3 = str.indexOf("xy");

System.out.println(idx3);    // 找不到时,返回-1

 

 

*/

/*

//5 lastIndexOf 查找位置  从后向前找

String str = "abcdeabcd";

 

int idx = str.lastIndexOf("cd");

System.out.println(idx);

 

int idx2 = str.lastIndexOf("ab",3);

System.out.println(idx2);

 

int idx3 = str.lastIndexOf("xy");

System.out.println(idx3);    // 找不到时,返回-1

*/

}

}

(4)转换功能方法  

  1. byte[] getBytes():将当前字符串,转成字节数组
  2. char[] toCharArray():将当前的字符串,转成字符数组
  3. toUpperCase():将当前的字符串,转成全大写形式
  4. toLowerCase():将当前的字符串,转成全小写形式
  5. concat(String str):将当前调用者,和参数str进行拼接,返回拼接后的长字符串(不常用,因为更多使用的是运算符+)
  6. valueOf家族:可以将任意数据类型的数据,转换成字符串

示例代码

public class Demo06_String类常用方法_转换功能的方法 {

public static void main(String[] args) {

/*

// 1 getBytes()  将字符串转换成字节数组

String str = "abcd";

byte[] b = str.getBytes();

for(byte bb:b){

System.out.println(bb);

}

*/

/*

// 2 toCharArray() 将字符串转成字符数组

String str = "abcd";

char[] cc = str.toCharArray();

 

for(char c:cc){

System.out.println(c);

}

*/

 

/*

// 3 toUpperCase 小写转大写

String str = "abcd";

 

String str2 = str.toUpperCase();

System.out.println(str2);

 

*/

/*

    //4 toLowerCase 大写转小写

String str = "AbCd";

String str2 = str.toLowerCase();

System.out.println(str2);

 

*/

 

/*

//5 concat 用来拼接字符串  和 +的作用相同 . 不同点: + 可以加任何类型   而concat只能拼接字符串

String s1 = "aaa";

String s2 = "bbb";

String s3= s1.concat(s2);

System.out.println(s3);

 

*/

/*

//6 valueOf 将其他类型转换成字符串   静态方法

 

int x = 100;

String str = String.valueOf(x);

System.out.println(str+1);  // "1001"

 

int y = 200;

String str2 = y+"";  //任何类型和字符串相加结果都是字符串

System.out.println(str2+1);  //"2001"

*/

}

}

练习

键盘录入一个大小写混杂的纯英文字符串。

将字符串转换成首字母大写,其他字母全部小写。

例如,键盘录入”i lOvE jAvA”,转换成 “I love java”

public class Demo07_l练习_首字母大写其他小写 {

/*

键盘录入一个大小写混杂的纯英文字符串

将字符串转换成首字母大写,其他字母全部小写

例如,键盘录入”i lOvE jAvA”,转换成 “I love java”

 * */

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

String str = sc.nextLine();  // 首字母转大写,其他小写

 

String s1 = str.substring(0,1); //截取首字母

String s2 = str.substring(1);   //截取其他

 

String result = s1.toUpperCase()+s2.toLowerCase();

System.out.println(result);

 

}

}

(5)其他方法

  1. replace(String oldStr, String newStr):将调用者中的旧串替换成新串
  2. trim():去掉字符串左右两边的空格、制表符
  3. split():字符串拆分

示例代码

public class Demo08_其他方法 {

 

public static void main(String[] args) {

/*

// replace 替换   replaceAll---后面讲

 

String str = "www.baidu.com";

 

String str2 = str.replace("w", "x");

System.out.println(str2);

 

 

String str3 = str.replace("www", "x");

System.out.println(str3);

 

*/

 

/*

// trim 去首尾空格

 

String str = "  aaa  bbb        ";

String str2 = str.trim();

System.out.println(str);

System.out.println(str2);

 

*/

/*

// split 字符串拆分   拆成数组

String str = "aaa#bbb#ccc#ddd";

String[] ss = str.split("#");

for(String s:ss){

 

System.out.println(s);

}

*/

 

 

/*

String str = "aaa##bbb#ccc#ddd";

String[] ss = str.split("#");

for(String s:ss){

 

System.out.println(s);

}

 

*/

String str = "aaa+bbb+ccc+ddd";

//String[] ss = str.split("+");  // 因为+是正则表达式(后面讲)的特殊字符    (+ . * ?)需要转义

String[] ss = str.split("\\+");

for(String s:ss){

 

System.out.println(s);

}

}

}

三、字符串缓冲区StringBuilder

1、概述

  1. StringBuilder是一个可变的字符序列,因为在类中提供了修改私有成员变量的方法。常用的方法是append和insert,就是在StringBuilder对象本身上,进行修改操作。
  2. StringBuilder底层和String类型一样,也是维护了一个字符数组,数组是私有的,外界无法直接访问,因此在StringBuilder或者String中对数组进行操作的公有方法的封装。
  3. String类型和StringBuilder的关系:都是用于描述字符串。

  1、String是不可变的字符序列,没有提供修改私有成员的方法;StringBuilder是可变的字符序列,因为提供了修改成员变量的方法;

2、String长度本身也不可以变化,StringBuilder长度可以变化,可以认为StringBuilder就像一个可以伸缩的容器,用于存储字符。

2、构造方法

  1. 构造方法作用:创建当前对象、将其他类型的数据,转换成当前类型。
  2. StringBuilder的构造方法:

  StringBuilder():创建一个生成器,初始容量为16个字符。

StringBuilder(int capacity):创建一个生成器,初始容量为capacity大小。

StringBuilder(String str):创建一个生成器,初始值就是str这些字符,初始大小是str+16。

  1. 获取容积的方法:

capacity():获取当前生成器的容器大小。

  length():获取当前生成器中的字符个数。

 

代码示例

public class Demo01_StringBuilder构造方法 {

public static void main(String[] args) {

/*

StringBuilder sb = new StringBuilder();

int length = sb.length();  // 获取sb中包含多少个字符

System.out.println(length);

int capacity = sb.capacity();  //获取容量  默认 16

System.out.println(capacity);

*/

StringBuilder sb = new StringBuilder("abc");

int length = sb.length();  // 获取sb中包含多少个字符

System.out.println(length);

int capacity = sb.capacity();  //获取容量  这种初始化方式     用字符串的长度+16

System.out.println(capacity);

}

}

3、添加功能

  1. append(任意类型):可以将任意数据类型,转成字符,添加到生成器中
  2. insert(int index, 任意数据类型):可以将任意数据类型,添加到指定的位置

说明:1、index的范围是0~当前缓冲区的大小;2、插入数据之后,数据本身的索引就是参数中指定的index

 

代码示例

public class Demo02_StringBuilder添加功能 {

public static void main(String[] args) {

StringBuilder sb = new StringBuilder("abc");

sb.append("xyz");  // 追加在末尾

System.out.println(sb);

sb.insert(1, "hello"); // 在相应的位置插入

System.out.println(sb);

}

}

4、删除功能

  1. deleteCharAt(int index) :删除指定索引的字符
  2. delete(int start, int end):删除指定范围的字符,被删除的部分包含头不包含尾

代码示例

public class Demo03_StringBuilder_删除功能 {

public static void main(String[] args) {

StringBuilder sb = new StringBuilder("abcdefg");

System.out.println(sb);

sb.deleteCharAt(1);

System.out.println(sb);

sb.delete(1,3); // 左闭右开

System.out.println(sb);

}

}

5、替换和反转功能

  1. replace(int start, int end ,String str):

将字符串缓冲区中的从start开始到end-1这部分内容,替换成str

  1. reverse():将原有字符序列进行反转

代码示例

public class Demo04_StringBuilder_替换和反转功能 {

public static void main(String[] args) {

StringBuilder sb = new StringBuilder("abcdefg");

//sb.reverse();  //反转

//System.out.println(sb);

sb.replace(1, 3, "hello");  //替换

System.out.println(sb);

}

}

6、练习

1、定义一个方法,接收一个String类型的字符串,返回该字符串的反转形式

举例:接收字符串为abc,返回字符串为cba

要求:使用StringBuilder进行反转,提高开发效率

代码示例

public class Demo05_练习_使用StringBuilder进行字符串反转 {

public static void main(String[] args) {

String str = "abc";

String result = fanzhuan(str);

System.out.println(result);

}

public static String fanzhuan(String str){

StringBuilder sb = new StringBuilder(str);

sb.reverse();// 反转——使用StringBuilder的reverse方法反转效率高

return sb.toString();  // 把StringBuilder转成String

}

}

7、String和StringBuilder拼接字符串的区别

使用String类型拼接字符串:时间和空间上都非常浪费。

  1、创建一个StringBuilder的存储空间,大小为第一个字符串的长度+16(第一个对象)

  2、将第一个字符串添加到缓冲区中

  3、将第二个字符串添加到缓冲区中

  4、将缓冲区对象转成字符串对象(创建了一个新的字符串对象)(第二个对象)

   5、返回该字符串对象

使用StringBuilder拼接字符串:时间和空间上都非常节省,无论循环多少次,都只创建两个对象。

  1、创建一个新的StringBuilder的存储空间

2、在StringBuilder的基础上进行添加,不创建新的字符串

3、循环完成后,将StringBuilder转成String

 

示例代码

/*

 * String 使用+拼接字符串时,底层会转换成StringBuilder。拼完后再转成String

 * 这样做内存中会创建更多的对象,而且转换过程也比较耗时。

 *

 * StringBuilder 使用append拼接字符串就不存在以上问题

 *

 * 当有大量的字符串需要拼接时,一定要使用StringBuilder

 *

 *

定义一个方法,接收一个int[]类型的数组,返回该数组的字符串表示形式

举例:接收数组为int[] arr = {1, 2, 3},返回的字符串为[1, 2, 3]

要求:使用StringBuilder进行拼接,提高运行效率

 *

 *

 * */

public static void main(String[] args) {

int[] aa = {1,2,3,4,5};

String str = arrStr(aa);

System.out.println(str);

}

public static String arrStr(int[] aa){

StringBuilder sb = new StringBuilder("[");

for(int i=0;i<aa.length;i++){

sb.append(aa[i]).append(i==aa.length-1?"]":",");

}

return sb.toString();

}

 

public static String arrStr2(int[] aa) {

String result = "[";

for (int i = 0; i < aa.length; i++) {

result += aa[i] + (i == aa.length - 1 ? "]" : ", ");

}

return result;

}

}

8、String和StringBuilder的相互转换

String转成StringBuilder

  1、StringBuilder的构造方法

  2、append方法

StringBuilder转成String类型

  1、toString的方法

  2、使用String的构造方法

代码示例

public static void main(String[] args) {

String str = "abc";

StringBuilder sb = new StringBuilder(str);

String result = sb.toString();

}

9、StringBuffer和StringBuilder的区别

相同点:

  都是字符串的缓冲区,都是字符串的生成器,都是可变的字符序列

不同点:

  1、出现版本不同:

    StringBuffer在jdk1.0出现的

    StringBuilder在jdk1.5出现的

  2、线程安全性不同:

    StringBuffer是线程安全的,在多线程环境下仍然保证数据安全

    StringBuilder是线程不安全,在多线程环境下无法保证数据安全

  3、效率不同:

    StringBuffer效率低

    StringBuilder效率高

10、String和StringBuilder作为方法的参数

  1. String作为方法的参数进行传递,无法修改原值。在被调用的方法中,修改引用指向的对象,和主方法中的引用无关。

  1. StringBuilder作为方法的参数进行传递,如果在被调用的方法中,修改的是StringBuilder的引用,那么不会改变原有对象中的数据。

 

  1. StringBuilder作为方法的参数进行传递,如果在被调用的方法中,通过该引用修改了对象的数据,那么原值就会发生改变。

 

代码示例

public class Demo09_String和StringBuilder作为方法参数问题 {

public static void main(String[] args) {

/*

String str = "abc";

update(str);

System.out.println(str);

*/

/*

StringBuilder sb = new StringBuilder("abc");

update2(sb);

System.out.println(sb);

*/

StringBuilder sb = new StringBuilder("abc");

update3(sb);

System.out.println(sb);

}

public static void update(String ss){

ss = "xyz";

}

public static void update2(StringBuilder ss){

ss = new StringBuilder("xyz");

}

public static void update3(StringBuilder ss){

ss.append("xyz");

}

}

11、字符串的比较 ==和equals总结

示例代码

public static void main(String[] args) {

/*

String str = "abc";                //常量池

String str2 = new String("abc");   //堆

System.out.println(str==str2);

*/

/*

String str = "aaa"+"bbb"; //常量优化机制——在编译时 就已经完成了 "aaa"+"bbb"的计算

String str2 = "aaabbb";

System.out.println(str==str2);

*/

/*

String str = "aaa";

str = str+"bbb";

String str2 = "aaabbb";

System.out.println(str==str2);

*/

/*

String s1 = "aaa";

String s2 = "bbb";

String str = s1+s2;

String str2 = "aaabbb";

System.out.println(str==str2);

*/

 

//String str = "aaa"+"bbb"; //常量优化机制,在编译器就完成了运算  str指向常量池中的 "aaabbb"

String str = "aaa";

str = str+"bbb";   

// 字符串使用+拼接时,一旦有变量参与,底层会转成StringBuilder 并使用append完成拼接。运算完成后,在转换成String返回。

// 而且,这个转换后的String存在堆区

}

作业

1、分析以下需求,并用代码实现:

(1)定义数字字符串数组{"010","3223","666","7890987","123123"}

(2)判断该数字字符串数组中的数字字符串是否是对称(第一个数字和最后一个数字相等,第二个数字和倒数第二个数字是相等的,依次类推)的,并逐个输出

(3)如:010 是对称的,3223 是对称的,123123 不是对称的

(4)最终打印该数组中对称字符串的个数

 

提示:循环获取字符串的每一个字符,依次比较第一个和最后一个,第二个和倒数第二个。。。

 

 

2.分析以下需求,并用代码实现:

(1)从键盘循环录入录入一个字符串,输入"end"表示结束

(2)将字符串中大写字母变成小写字母,小写字母变成大写字母,其它字符用"*"代替,并统计字母的个数

举例:

键盘录入:Hello12345World

输出结果:hELLO*****wORLD

  总共10个字母

 

3、键盘录入一个字符串,统计该字符串中的大写字母、小写字母、数字字符和其他字符分别有多少个

例如,键盘录入abcABCD12345!@#$%&,输出结果为:小写字母有3个,大写字母有4个,数字字符有5个,其他字符有6个。

 

4、定义一个方法,功能如下:给定一个数组,转换成一个字符串

例如:数组为int[] arr = {1, 2, 3},字符串为[1, 2, 3]

 

5、定义一个方法,功能如下:给定一个字符串,返回该字符串的反转形式

例如:字符串为abcdef,返回结果为fedcba

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值