Java第十一课. 核心API02-String

Java第十一课. 核心API02-String

回顾

1. lang包:java内置的基础包,程序会帮我们自动导入;
2. enum:安全检查功能,规范参数值;
3. 包装类:8
ByteShortIntegerLongFloatDoubleBooleanCharacter
byteshortintlongfloatdoublebooleanchar
4. 为什么要使用包装类,他是为了替代基本数据类型吗?
    1. 和面向对象的思想一致,基本数据类型没有方法属性;
	2. 和其它数据类型转换,需要用到包装类中的方法;
	3. 不是替代,只是有些场合基本数据类型使用不了,比如集合;
5. 自动拆箱:自动将 包装类  变成  基本数据类型;
   自动装箱:自动将 基本数据类型  变成  包装类;
	jdk1.5 以上才支持自动拆装箱::Integer i=10;int a=i;:int a=1,Integer i=a;
6. Integer:将字符串转成整数:int a=Integer.parselnt(string);
						 Integer i=Integer.valueOf(string)
7. Character:判断是字母,数字,大写,小写
8. String: charAt(int index)  contains()  equals()  length()
    isEmpty()   valueOf(int i)   equalsIgnoreCase(String anotherSring)   toUpperCase()  toLowerCase()

1. String

1.1 [面试题] String的==和equals()判断方法
1. ==判断的是两个字符串的[地址]是否相同;
2. equals(ObjectanObjct)判断的是两个[字符串的内容]是否相同;
//[注]:1.Object类的equals()方法,其实是判断地址,而不是内容;

在这里插入图片描述

String 继承 Object 类,重写了equals方法,变成了判断的是字符串的内容;

//注意:关于equals()方法的代码规范:尽量使用非空对象来调用equals()方法.避免出现空指针异常;
public class TestString01 extends Object{

	public static void main(String[] args) {
		//从前端接收到一个用户名,我们想判断值是否是admin
		String username=null;
		//if (username.equals("admin")) {
		if ("admin".equals(username)) {
			System.out.println("admin登录");
		}else {
			System.out.println("登录失败");
		}

		Person person=new Person("张三", 0);
		Person person2=new Person("张三", 0);
		System.out.println(person==person2);//false
		System.out.println(person.equals(person2));//false
	}//只有String方法重写了equals方法

}
1.2 [面试题] String的不可变性
1. String 在JDk源码中,该类是被 final 修饰,不可被继承;
   String 底层是字符数组,被 final 修饰,表示不可变。

在这里插入图片描述

2. 用代码演示不变性

在这里插入图片描述

1.3 [面试题] String拼接问题
public class TestString03 {

	public static void main(String[] args) {
		//关于String拼接的问题
		String string="A";
		for (int i = 0; i < 9; i++) {
			string+=i;//此做法,会不断生成新的对象,会造成内存资源的浪费,可以通过debug打点看出
		}
		System.out.println(string);
	}

}
[注意]:不能使用String进行字符串的拼接动作;

2. 类 StringBuffer

2.1 概念
[概念]:[线程安全的可变字符序列]。一个类似于 String 的字符串缓冲区,但[能修改]。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
构造方法摘要
StringBuffer 构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。
StringBuffer(String str) 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容
2.2 常见方法:
intcapacity() 返回当前容量
StringBufferappend(String str) 将指定的字符串追加到此字符序列
charcharAt(int index) 返回此序列中指定索引处的 char 值
StringBufferreverse() 将此字符序列用其反转形式取代
public class TestStringBuffer {

	public static void main(String[] args) {
		// 创建一个StringBuffer对象
		StringBuffer sBuffer=new StringBuffer("abc");
		sBuffer.append("xyz");
		System.out.println(sBuffer);//abcxyz
		
		String string=new String("abc");
		string="xyz";
		System.out.println(string);//xyz
		
	}

}

3. 类 StringBuilder

3.1 概念
一个可变的字符序列。这个类提供了一个API兼容StringBuffer,但无法保证同步.非线程安全;
构造方法
StringBuilder() 构造一个没有字符的字符串生成器,并构造了16个字符的初始容量。
StringBuilder(String str) 构造一个初始化为指定字符串的内容的字符串生成器。
public class TestStringBuilder {

	public static void main(String[] args) {
		StringBuilder sBuilder=new StringBuilder("xyz");
	}
}

4.【面试题:String和StringBuffer和StringBuilder】

4.1 问题: StringBuffer/ StringBuilder和String区别
StringStringBufferStringBuilder
是否可变不可变可变可变
线程同步安全不同步同步不同步
4.2 问题: StringBuffer/ StringBuilder和String如何转换
public class TestChange {

	public static void main(String[] args) {
		//将String转换成StringBuffer与StringBuilder
		String string="abc";
		StringBuffer sbBuffer=new StringBuffer(string);
		StringBuilder sBuilder=new StringBuilder(string);
		System.out.println(sbBuffer.getClass().getName());//java.lang.StringBuffer
		System.out.println(sBuilder.getClass().getName());//java.lang.StringBuilder
		
		//怎么将StringBuffer与StringBuilder转成String
		String string2=sbBuffer.toString();
		System.out.println(string2.getClass().getName());//java.lang.String
		String string3=sBuilder.toString();
		
	}

}
4.3 问题: StringBuffer和StringBuilder相比为什么支持线程同步
StringBuffer:有一个线程同步的关键字,效率比较低,相对安全;

在这里插入图片描述

StringBuilder:无线程同步的关键字,效率高;
synchronized :用于指定多线程代码中的同步方法、变量或者代码块。

在这里插入图片描述

StringBuffer 与 StringBuilder 共同特征:可变性;
    						  不同:一个线程安全,一个非线程安全;

//当有多个线程同时对一个字符串操作,StringBuffer因为有线程同步关键字,相当于上了一把锁,只有当其中一个线程操作完成,锁才会打开,下一个线程才能对其操作,所以效率较低,但相对安全;反之StringBuilder因为没有关键字,所以效率高,非线程安全;

5.方法的参数传递

5.1 基本数据类型作为参数【值传递】
public class MethodParameterTest {

	public void changeInt(int a) {//形参
		//改变
		a=a+2;
		System.out.println("changeInt:a="+a);//3
	}
    
    public static void main(String[] args) {
		MethodParameterTest mp=new MethodParameterTest();
		System.out.println("----基本数据类型作为参数【值传递】------");
		int a=1;
		mp.changeInt(a);//实参,将a的值拷贝一份给方法changeInt()的形参,值传递
		System.out.println("main:a="+a);//1
        
    }
}

基本数据类型作为参数,传递的是值的一个副本给形参,在方法内对形参的操作,不影响实参的值。

5.2 引用数据类型(数组、类)作为参数【引用传递】

将数组作为参数:

/**
	 * 数组作为参数
	 * @param args
	 */
	public void changeArray(int[] array) {
		//改变数组的内容,将数组中的每一个元素*2
		for (int i = 0; i < array.length; i++) {
			array[i]=array[i]*2;
		}
		//再一次输出
		for (int i = 0; i < array.length; i++) {
			System.out.print("changeArray:数组元素:"+array[i]+" ");
		}
	}

测试类:

System.out.println("----数组作为参数【引用传递】------");
		int[] array= {1,2,3};//array引用名在栈中,{1,2,3}真正的值在堆中
		mp.changeArray(array);//2 4 6 将array引用名[堆的地址]传递给方法changeArray()的形参array,
		//和当前形参,两个引用名其实指向的是堆中的同一个对象
		for (int i = 0; i < array.length; i++) {
			System.out.print("mainArray:数组元素:"+array[i]+" "); //2 4 6
		}

在这里插入图片描述
把类作为参数:

/**
	 * 将类作为参数
	 * 自定义Dog 
	 * 
	 */
	public void changeObject(Dog dog) {
		//dog=new Dog();//如果重新new   就是一个新的对象
		dog.setName("哈巴狗");
		System.out.println("changeObject 狗信息:"+dog.getName()); //哈巴狗
	}

测试类:

	System.out.println("------类作为参数传递[引用传递]---------");
    Dog dog=new Dog();
    dog.setName("哈士奇");
    mp.changeObject(dog);
    System.out.println("main:狗信息"+dog.getName()); //哈巴狗

原理和上面数组传参一样

数组、类等引用数据类型作为参数,传递的引用名的值其实是堆的地址给形参,则实参和形参两个引用名指向堆中的同一个对象,在方法体中对该地址中的值改变就会影响实参。

5.3 Sting字符串作为参数【值传递】

函数定义和函数调用:

/**
	 * 字符串String 引用类型作为参数 值传递
	 * @param args
	 */
	public void changeString(String str) {
		str="world";//对str重新赋值,会重新开辟一个对象
		System.out.println("changeString:str="+str);//world
	}

测试类:

	System.out.println("----String作为参数【值传递】------");
    String str="Hello";
    mp.changeString(str);
    System.out.println("main:str="+str);//Hello

在这里插入图片描述

String传递的时候,其实也是将实参引用名中的堆的地址传递给形参,因为String具有不可变性,当方法体内对该地址的字符串重新赋值,则相当于在内存在重新创建了一个对象,不影响实参。

6. 总结:[值传递与引用传递]

[值传递]
(形式参数类型是基本数据类型):
方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。

[引用传递]
(形式参数类型是引用数据类型参数):
也称为传地址。方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。

练习

public class TestMethod {
	public static void main(String[] args) {
		String s1="abc";
		String s2="xyz";
		changeStr(s1, s2);//值传递
		System.out.println("执行方法后"+s1+"----"+s2);//abc  xyz
		
		System.out.println();
		
		StringBuffer sb1=new StringBuffer("abc");
		StringBuffer sb2=new StringBuffer("xyz");
		changeStr(sb1, sb2);//引用传递  
		
		System.out.println("执行方法后"+sb1+"----"+sb2);//(=不会改变内容,而改变指向)abc----xyzxyz
	}
	
	public static void changeStr(StringBuffer sb1,StringBuffer sb2) {
		sb1=sb2;//sb1和sb2的指向是一致的,在方法内,sb1临时指向 了sb2的内存xyz
		sb2.append(sb1);  //sb2=xyz sb1=xyz  经过append()sb2指向的内存对象又追加了xyz->xyzxyz
		System.out.println("方法中:"+sb1+"----"+sb2);// xyzxyz----xyzxyz
	}
	
	public static void changeStr(String s1,String s2) {
		s1=s2;//s1和s2的指向是一致的,指向xyz
		s2=s1+s2;
		System.out.println("方法中:"+s1+"----"+s2);//xyz  xyzxyz
	}
	
}

方法中:xyz----xyzxyz
执行方法后abc----xyz

方法中:xyzxyz----xyzxyz
执行方法后abc----xyzxyz

在这里插入图片描述
在这里插入图片描述

7. 字符串类小结:

1)  String 和 StringBuffer 、 StringBuilder 相比, String 是不可变的, String 的每次修改操作都是在内存中重新 new 一个对象出来,而 StringBuffer 、 StringBuilder 则不用,并且提供了一定的缓存功能,默认16个字节数组的大小,超过默认的数组长度时,则扩容为原来字节数组的长度*2+22) StringBuffer 和 StringBuilder 相比, StringBuffer 是 synchronized 的,是线程安全的,而 StringBuilder 是非线程安全的,单线程情况下性能更好一点;使用 StringBuffer 和 StringBuilder 时,可以适当考虑下初始化大小,减少扩容的次数,提高代码的高效性。
3)	方法传递:值传递(将基本数据类型, String 作为参数)->形参与实参的值互不影响,引用传递(将引用类型作为参数)->形参与实参的值相互影响;

8. 练习

1.编写一个程序,将下面的一段文本中的各个单词的字母顺序翻转,
    “To be or not to be",将变成"oT eb ro ton ot eb."。
    1)split(" ")-根据空格split;
    2)遍历每一个元素,然后反转;
public class Testhw01 {

	/**
	 * 1.编写一个程序,将下面的一段文本中的各个单词的字母顺序翻转,
	  	“To be or not to be",将变成"oT eb ro ton ot eb."。
	    	1)split(" ")-根据空格split
	  	    2)遍历每一个元素,然后反转
	 */
	@Test
	public void test01() {
		String string="To be or not to be";
		String[] strs=string.split(" ");//通过空格去拆分,因为to be之间是空格,如果是to,be,参数就为","
		//System.out.println("长度:"+strs.length);//6
		
		for (int i = 0; i < strs.length; i++) {
			//System.out.println(strs[i]);
			StringBuilder sBuilder=new StringBuilder(strs[i]);
			//System.out.print(sBuilder.reverse()+" ");
			System.out.print(sBuilder.reverse().append(" "));
		}
		
		
	}
}

oT eb ro ton ot eb 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值