java-day15

Day15-常用API

1. String

1.1 概述
java.lang.String : 字符串类,并且该类加 final修饰

底层就是char数组 private final char value[];
所以 字符串很多特性 就是数组的特性
1 字符串一旦创建不可更改

2 为了提升字符串的访问效率,Java中提出了字符串常量池,相当于是一个缓存区
引用类型对象应该保存在堆内存,但是字符串不同,保存在静态区的字符串常量池中

3 在程序的执行过程中,如果程序要用到某个字符串,如"abc",虚拟机会先去常量池中搜索,有没有这个字符串

如果已经有了,就直接指向该字符串即可,如果没有就新建一个字符串对象,并指向
在这里插入图片描述
1.2 基本使用

package com.demo.String;

/**
 * String 会有个常量池,当有个一样的值会去从常量池找,所以找到的地址相同,没有的话就new String()在堆中建立新的内存地址,并且在常量池也会有这个值
 * */
public class String_01 {

	public static void main(String[] args) {
		// 第一部分
		String s1 = "abc";
		// 这里并没有改变字符串abc的值,而是新建了一个字符串叫a2 并让s1指向a2
		s1 = "a2";
		System.out.println(s1);
		
		// 第二部分 
		String s2 = "abc";
		String s3 = "abc";
		String s4 = "Abc";
		// true , == 比较基本类型比较值,比较引用类型比较内存地址
		// 而 s2 和 s3 指向的地址 是相同的
		System.out.println(s2 == s3);
		// 创建两个对象,abc和Abc
		// true  比较的是值
		System.out.println(s2.equals(s3));
		
		// 第三部分
		// new的方式,s5不再指向常量池,而是指向堆内存对象,堆内存中保存常量池的地址
		String s5 = new String("123");
		String s6 = new String("123");
		// 以上两句 : 创建三个对象(堆内存两个,常量池一个),占用5块空间(栈内存两个,堆内存两个,常量池一个)
		// == 就是在比较 堆内存地址,而不是常量池中 123的地址了,因为new了两次,所以不一致
		System.out.println(s5 == s6);
		System.out.println(s5.equals(s6));
	}
}

1.3 不要频繁使用拼接

package com.demo.String;

/**
 * 由于String数组 继承了数组的特性,一旦创建了了就不能修改
 * 因为String一旦创建不可更改,
 * 所以使用的时候,要注意,不要频繁拼接字符串,因为效率比较低,还浪费空间,并且垃圾回收也会有一定问题
 * 
 
 */
public class String_02 {

	public static void main(String[] args) {
		String[] strs = {"a","b","c","d"};
		String tmp = ""; 
		
		for (String string : strs) {
			tmp+=string;
		}
		//虽然拼接了abcd 但是在之前的还有 a ab abc 这三个在内存中
		System.out.println(tmp);//abcd
		
	}
}

1.4 String构造方法

package com.demo.String;

/**
 * String中常用构造方法
 *
 * 创建String对象的方式
 * 

 */
public class String_03 {

	public static void main(String[] args) {
		// 1
		String s1 = "abc";

		// 2
		String s2 = new String("xxx");

		// 3 字节数组
		// byte[] aaa = {1,2,3};
		// byte[] aaa = new byte[]{1,2,3,4};//这种写法,少用了一个aaa变量进行传参
		// byte[] aaa = new byte[5];
		
		byte[] aaa = { 97, 98, 99 };
		String s3 = new String(aaa);
		//不能这样传入一维数组
//		System.out.println({97, 98, 99});
		String s4 = new String(new byte[] { 97, 98, 99 });
		// abc : 因为把数字转换为char  97 就是a 
		System.out.println(s4);//abc,int型转化为char型,ASCII码值

		// 4 字节数组 , 截取一部分
		// 从下标 1 开始(包含),取两个
		String s5 = new String(aaa, 1, 2);
		System.out.println(s5);//bc
		
		// 5 字符数组
		char[] chars = {'a','b','c','d'};
		String s6 = new String(chars);
		System.out.println(s6);//abcd
		// 6 截取一部分
		String s7 = new String(chars,2,2);
		System.out.println(s7);//cd
		
		// 7 无参 空字符串
		String s8 = new String();
		System.out.println(s8);
	}
}

1.5 常用方法

package com.demo.String;

/**
 * String常用方法
 * 
 * 1 方法是谁的(这里肯定是String)
 * 
 * 2 什么方法,静态还是成员,知道是什么方法,就知道应该如何调用
 * 
 * 3 方法名是什么,入参和出参是什么
 * 
 * 4 方法功能是什么
 * 

 */
public class String_04 {

	public static void main(String[] args) {
		// 1 int length() : 返回该字符串长度
		String s1 = "qwert!";
		System.out.println(s1.length()); // 6
		
		// 2 char charAt(int index) : 获取字符串某个位置上的字符
		char c1 = s1.charAt(2);
		System.out.println(c1); // e
		
		// 3 boolean endsWith(String suffix) :  判断字符串是否以指定字符串结尾
		// boolean startsWith(String prefix) : 判断字符串是否以指定自己开始
		System.out.println("HelloWord.java".endsWith(".java"));// true
		System.out.println("HelloWord.java".endsWith(".java "));// false 有空格
		
		// 4 boolean equalsIgnoreCase(String anotherString) : 不区分大小写比较两个字符串是否相等
		System.out.println("abc".equals("AbC")); // false
		System.out.println("abc".equalsIgnoreCase("AbC")); // true
		
		// 5 byte[] getBytes() : 把字符串转换为字节数组
		byte[] byteArr = "abc".getBytes();
		for (byte b : byteArr) {
			System.out.println(b);
		}
		System.out.println("----------");
		
		// 6 int indexOf(String str) : 获取指定字符串的起始索引值,找不到返回-1,如果有多个 ,找到第一个就不找了
		System.out.println("abcdce".indexOf("cd"));
		
		// 7 int indexOf(String str,int fromIndex) : 从指定位置开始找(包含),找不到返回-1
		System.out.println("abcdeabc".indexOf("a",1));
		
		// 8 int lastIndexOf(String str) : 获取最后一次出现的位置,找不到返回-1(倒着遍历,第一次出现,就是最后一次)
		//  int lastIndexOf(String str,int fromIndex) : 获取最后一次出现的位置,找不到返回-1,从指定位置反向搜索,第一次出现的位置
		System.out.println("abcdeabc".lastIndexOf("a"));
		
		// 9 String replaceAll(String regex, String replacement) : 把一个字符串替换为指定字符串
		// 一个类似的  replace : 这两个功能是一样的,只不过 replace 不支持正则表达式
		System.out.println("123321".replaceAll("1", "a")); // a2332a
		System.out.println("1.2.3".replaceAll(".", "-")); // ----- , 因为 会把 . 解析为正则表达式,而 . 代表 任何字符
		// 1-2-3 , 正则表达式中 可以通过 \ 把 .  转义为无意义字符,但是在java中 \ 是转移符,所以 要写 \\ 对\进行转义才可以
		System.out.println("1.2.3".replaceAll("\\.", "-")); 
		System.out.println("1.2.3".replace(".", "-")); // 1-2-3  , 因为不支持正则表达式,所以 . 就是 .
		
		
		// 10 String[] split(String regex) : 分割字符串,通过指定分隔符,来分割字符串,返回分割后的新字符串数组,支持正则表达式
		String myTime = "2021-1-20";
		String[] myTimes = myTime.split("-");
		for (String string : myTimes) {
			System.out.println(string);
		}
		System.out.println("==========");
		
		// 11 String substring(int begin) : 获取该字符从某个下标开始到结尾的子字符串(包含)
		System.out.println("abcde".substring(3));
		
		// 12 String substring(int beginIndex,int endIndex) : 获取该字符从某个下标开始(包含) 到某个下标结束的子字符串(不包含)
		System.out.println("qwerttyuyikjn".substring(3, 6));
		
		// 13 char[] toCharArray() : 转换为字符数组
		char[] c2 = "abc".toCharArray();
		for (char c : c2) {
			System.out.println(c);
		}
		System.out.println("+++++++++++++++");
		
		// 14 String toUpperCase() : 转为大写
		System.out.println("asdDGDHshdjbsaj".toUpperCase());
		// 15 String toLowerCase() : 转为小写
		System.out.println("asdDGDHshdjbsaj".toLowerCase());
		
		// 16 String trim() : 删除字符串两边的空格
		System.out.println("              ab              cd                      ");
		System.out.println("              ab              cd                      ".trim());
		
		// 17 static String valueOf(Object obj) : 调用指定对象的toString方法,并且 避免了空指针异常
		// (obj == null) ? "null" : obj.toString();
		String_04 ss = null;
		System.out.println(ss);
		
	}
}

1.6 注意
String 不可以任意拼接的字符串

String s2 = “a” + “b”; 这种写法,在编译阶段,就会把+ 去掉
“a” +“b” a和b都是字面量,需要在编译阶段说明临时空间,所以需要通过值确定类型
编译时看到是两个字符串相加,就直接把+省略,保存ab
所以 s1 ==s2 是true

String s3 = a + b;
a和b是变量,编译阶段是不确定变量的值的
在运行的时候,由于是两个字符串变量相加,
所以会自动创建一个StringBuffer对象,然后把两个变量拼接到一起,最终转换为String类型
而是以 return new String(value, 0, count); 所以 s3是指向堆内存的

package com.demo.String;

/**
 * java.lang.StringBuffer
 * 
 * java.lang.StringBuilder
 * 
 * 1 StringBuffer和StringBuilder是什么?
 * 			是一个可变的字符串缓冲区
 * 2 原理
 * 			预先在内存中申请一块空间,可以容纳字符序列(字符数组)
 * 			如果 预留空间不够,会进行自动扩容
 * 			底层都是char[] ,并且默认初始化容量是16个字符
 * 
 * 3 String,StringBuffer,StringBuilder最大的区别
 * 			1 String不可变字符序列,而StringBuilder和StringBuffer是可变字符序列
 * 			2 StringBuffer是线程安全,在多线程环境下,不会出现问题,所以效率低,一般常用于类中
 * 			3 StringBuilder是非线程安全,在多线程环境下可能出现问题,效率高,一般用于方法中
 * 	4 如何选择StringBuilder和StringBuffer
 * 			多线程环境下,是否有可能出现多个线程同时操作同一个数据 的可能(增,删,改)
 * 

 */
public class String_05 {

	public static void main(String[] args) {
		StringBuffer sb = new StringBuffer();
		String[] strs = {"a","b","c","d"};
		for (String string : strs) {
			sb.append(string).append(".");//.;可用于字符串凭借
		}
		// 引用类型转String  调用toString方法
		String str = sb.toString();
		System.out.println(str);//a.b.c.d.
		
		StringBuilder sbr = new StringBuilder();
		for (String string : strs) {
			sbr.append(string);
		}
		System.out.println(sbr.toString());//abcd
		//反转
		System.out.println(sbr.reverse());//dcba
	}
}

StringBuilder 和 StringBuffer

2.1 概述
java.lang.StringBuffer

java.lang.StringBuilder

1 StringBuffer和StringBuilder是什么?
是一个可变的字符串缓冲区
2 原理
预先在内存中申请一块空间,可以容纳字符序列(字符数组)
如果 预留空间不够,会进行自动扩容
底层都是char[] ,并且默认初始化容量是16个字符

3 String,StringBuffer,StringBuilder最大的区别
1 String不可变字符序列,而StringBuilder和StringBuffer是可变字符序列
2 StringBuffer是线程安全,在多线程环境下,不会出现问题,所以效率低,一般常用于类中
3 StringBuilder是非线程安全,在多线程环境下可能出现问题,效率高,一般用于方法中
4 如何选择StringBuilder和StringBuffer
多线程环境下,是否有可能出现多个线程同时操作同一个数据 的可能(增,删,改)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.3 使用

package com.demo.String;

/**
 * java.lang.StringBuffer
 * 
 * java.lang.StringBuilder
 * 
 * 1 StringBuffer和StringBuilder是什么?
 * 			是一个可变的字符串缓冲区
 * 2 原理
 * 			预先在内存中申请一块空间,可以容纳字符序列(字符数组)
 * 			如果 预留空间不够,会进行自动扩容
 * 			底层都是char[] ,并且默认初始化容量是16个字符
 * 
 * 3 String,StringBuffer,StringBuilder最大的区别
 * 			1 String不可变字符序列,而StringBuilder和StringBuffer是可变字符序列
 * 			2 StringBuffer是线程安全,在多线程环境下,不会出现问题,所以效率低,一般常用于类中
 * 			3 StringBuilder是非线程安全,在多线程环境下可能出现问题,效率高,一般用于方法中
 * 	4 如何选择StringBuilder和StringBuffer
 * 			多线程环境下,是否有可能出现多个线程同时操作同一个数据 的可能(增,删,改)
 * 

 */
public class String_05 {

	public static void main(String[] args) {
		StringBuffer sb = new StringBuffer();
		String[] strs = {"a","b","c","d"};
		for (String string : strs) {
			sb.append(string).append(".");//.;可用于字符串凭借
		}
		// 引用类型转String  调用toString方法
		String str = sb.toString();
		System.out.println(str);//a.b.c.d.
		
		StringBuilder sbr = new StringBuilder();
		for (String string : strs) {
			sbr.append(string);
		}
		System.out.println(sbr.toString());//abcd
		//反转
		System.out.println(sbr.reverse());//dcba
	}
}

3. 包装类

3.1 概述
包装类 : 封装了基本类型的操作,更方便我们使用

byte – java.lang.Byte
short – java.lang.Short
int – java.lang.Integer
long – java.lang.Long
float – java.lang.Float
double – java.lang.Double
char – java.lang.Character
boolean – java.lang.Boolean

既然有了基本类型,为什么还要使用包装类呢?
1 方便
2 为了理论上的完整(面向对象)

问 : 想要创建一个方法,该方法可以接收任何类型
Object ,因为Object是所有类的祖类,由于多态的原因,可以接收任何对象
但是基本类型呢? 基本类型并不是Object的子类,怎么接收?
包装类 , 可以把基本类型转换为对应的包装类类型,而包装类也是个类,也是Object的子类

3.2 使用

package com.demo.Integer;

/**
 * 包装类 : 封装了基本类型的操作,更方便我们使用
 * 
 * 		byte -- java.lang.Byte
 * 		short -- java.lang.Short
 * 		int  -- java.lang.Integer
 * 		long -- java.lang.Long
 * 		float -- java.lang.Float
 * 		double  -- java.lang.Double
 * 		char  -- java.lang.Character
 * 		boolean -- java.lang.Boolean
 * 
 * 既然有了基本类型,为什么还要使用包装类呢?
 * 			1 方便
 * 			2 为了理论上的完整(面向对象)
 * 
 * 问 : 想要创建一个方法,该方法可以接收任何类型
 * 		Object ,因为Object是所有类的祖类,由于多态的原因,可以接收任何对象
 * 			但是基本类型呢? 基本类型并不是Object的子类,怎么接收?
 * 			包装类 ,  可以把基本类型转换为对应的包装类类型,而包装类也是个类,也是Object的子类
 * 
 
 */
public class Integer_01 {
	public static void main(String[] args) {
		// 基本类型
		byte b1 = 2;
		// 引用类型
		Byte b2 = null;
		// 把 b1 基本类型封装到b2引用类型中
		b2 = new Byte(b1);
		
		// 可以把b2 传入 接收Object的方法中,因为多态 Object b2 = new Byte();
		m1(b2);
	}
	public static void m1(Object obj){
		// 由于 覆写了toString方法,所以可以直接打印 2 ,而不是内存地址
		System.out.println(obj);//2
	}
}

3.3 Integer

3.3.1 基本使用

package com.demo.Integer;

/**
 * 以Integer为例 讲解八种包装类
 * 

 */
public class Integer_02 {

	public static void main(String[] args) {
		// 1 获取最大值和最小值
		System.out.println("int最大值 : " + Integer.MAX_VALUE);//2147483647
		System.out.println("int最小值 : " + Integer.MIN_VALUE);//-2147483648
		System.out.println("long最大值 : " + Long.MAX_VALUE);//9223372036854775807
		System.out.println("long最小值 : " + Long.MIN_VALUE);//-9223372036854775808
		System.out.println(Short.MAX_VALUE);//32767
		System.out.println(Short.MIN_VALUE);//-32768
		System.out.println((int) (Character.MAX_VALUE));//65535
		System.out.println((int) (Character.MIN_VALUE));//0
		
		// 2 创建对象
		Integer i1 = new Integer(12); // int -- Integer
		// 可以传入纯数字的字符串
		Integer i2 = new Integer("19776"); // String -- Integer
		
		System.out.println(i1);//12
		System.out.println(i2);//19776
		// 编译可以通过,但是运行出错
		// java.lang.NumberFormatException: For input string: "19776a"
//		Integer ie = new Integer("19776a");
	}
}

3.3.2 常用方法
在这里插入图片描述

package com.demo.Integer;

/**
 * 常用方法
 * 

 */
public class Integer_03 {

	public static void main(String[] args) {
		// 1 int --> Integer
		Integer i1 = new Integer(22);

		// 2 Integer --> int
		int i2 = i1.intValue();

		// 3 重要 : static int parseInt(String s) : 把字符串转换为int
		// String --> int
		int i3 = Integer.parseInt("123");
		System.out.println(i3);//123 整形

		// 4 重要
		double d1 = Double.parseDouble("12.3");
		System.out.println(d1);//12.3

		// 5 static String toBinaryString(int value) : 把指定int值转换为二进制的字符串形式展示
		String s1 = Integer.toBinaryString(10);
		System.out.println(s1);//1010

		// 6 十六进制展示
		System.out.println(Integer.toHexString(30));//1e
		// 7 八进制展示
		System.out.println(Integer.toOctalString(10));//12
		
		// 8 int --> Integer 
		Integer i31 = Integer.valueOf(28);
		// String --> Integer
		Integer i32 = Integer.valueOf("123");
		
		// 9 Integer -- String
		String s2 = i31.toString();
		System.out.println(i31);//28
		System.out.println(s2);//28
	}
}

3.3.3 类型转换

package com.demo.Integer;

/**
 * 类型转换
 * 
 * Integer , int , String 三者之间 相互转换
 * 

 */
public class Integer_04 {

	public static void main(String[] args) {
		// 1 int -- > Integer
		Integer i1 = new Integer(222);
		Integer i2 = Integer.valueOf(222);
		
		// 2 Integer --> int
		int i3 = i2.intValue();

		// 3 String --> Integer
		Integer i4 =  Integer.valueOf("123");
		Integer i5 = new Integer("12313");

		// 4 Integer --> String
		String s1 = i5.toString();

		// 5 String --> int
		int i6 = Integer.parseInt("12321");

		// 6 int --> String
		String s2 = 333+"";
	}
}

3.3.4 自动装箱和自动拆箱
java1.5新特性

自动装箱
把 基本数据类型 自动转换为 对应的包装类

自动拆箱
把 包装类 自动转换为 基本数据类型

自动装箱和自动拆箱是编译时 完成的

package com.demo.Integer;

/**
 * java1.5新特性
 * 
 * 		自动装箱
 * 				把 基本数据类型 自动转换为 对应的包装类
 * 		
 * 		自动拆箱
 * 				把 包装类 自动转换为 基本数据类型
 * 
 * 自动装箱和自动拆箱是编译时 完成的
 * 

 */
public class Integer_05 {

	public static void main(String[] args) {
		
		// 1.5之前
		// 自动装箱之前的转换方式
		Integer i1 = new Integer(223); // Integer.vlaueOf(2222)
		// 自动拆箱之前的转换方式
		int i3 = i1.intValue();
		
		
		// 1.5 开始
		// 自动装箱之后的转换方式
		Integer i2 = 222;  // 编译完后 就等于是 : Integer i2  = Integer.vlaueOf(222);
		// 自动拆箱之后的转换方式
		int i4 = i1; // 拆箱
		
		// 2 是基本类型,会先自动装箱转换为Integer类型,然后再向上转型(多态) 转换为Object
		m1(2);
	}
	public static void m1(Object obj){
		// 由于 覆写了toString方法,所以可以直接打印 2 ,而不是内存地址
		System.out.println(obj);
	}
}

3.3.5 扩展之整型常量池

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

大概意思是 : 这是一个缓存机制,如果值再-128到127之间,就不再创建新对象,而是直接把数组中的引用赋值给你
如果不再这个范围内,就创建 新的Integer对象

package com.demo.Integer;


/**
 * 深入理解自动装箱和自动拆箱
 * 
 * 		1 都是编译时的概念,和运行时无关
 * 		2 装箱的时候,会在编译时 自动把赋值 操作 变成 Integer.valueOf(222)
 * 
 * String , Integer,Double 等 八种包装类 和String 都覆写了toString(),equals() , hashCode() 方法
 * 
 * Integer.valueOf(xxx) : 方法实现
	  		    public static Integer valueOf(int i) {
	        		if (i >= IntegerCache.low && i <= IntegerCache.high)
	            		return IntegerCache.cache[i + (-IntegerCache.low)];
	        		return new Integer(i);
	    		}

 * 
 * 		valueOf : 把基本类型转换为Integer类型
 * 
 * 		但是里面初始化了一个整型常量池,值的范围是在 -128~127之间
 * 		其实  就是一个Integer[] 数组 有 256个对象,对象中的int值 分别为 -128,-127.....126,127  下标 是 0~ 255
 * 				在  private static class IntegerCache 类中 是 Integer中的一个静态内部类
 * 							三个变量 
 * 									       static final int low = -128;
        									static final int high;
        									static final Integer cache[];
        					并且在 static 代码块中 对这个数组进行了初始化操作
        					
 * 		如果 值 在 -128~127之间 就直接去这个缓存数组中找对应的对象即可,不用再重新创建Integer对象
 * 			   return IntegerCache.cache[i + (-IntegerCache.low)];  
 * 					// IntegerCache.low 是 -128   
 * 					// (-IntegerCache.low) : 就是 128  负负得正
 * 					// 加上 我们要添加的数据,就能得到 对应的值所在缓存数组中的下标索引
 * 					// 把该对象返回
 * 
 * 		那么这样的话,如果是通过自动装箱或者是通过valueOf方法赋值的两个值都符合该范围,那么 这两个变量保存的内存地址是一致的,则使用 == 也是true
 * 			如  Integer i1 = 123;  Integer i2 = 123;  或者 Integer i3 = Integer.valueOf(123);  他们的内存地址是相等的,找到的是同一个对象
 * 
 * 		反之 , 就等于new Integer(xxx)
 *			 	 return new Integer(i);  既然是new  那么 堆内存会重新创建新的对象,那么尽管初始化的int值一样,但是内存地址也不同
 *					所以 使用 == 也是false,此时 应该使用equals 来比较是否相等
 *				如 Integer i4 = Integer.valueOf(128);  Integer i5 = Integer.valueOf(128);    或者是 Integer i6 = new Integer(1) 

 */
public class Integer_06 {

	public static void main(String[] args) {
		
		// 自动装箱 , 就等于 Integer i1 = Integer.valueOf(123);
		Integer i1 = 123;
		Integer i2 = 123;
		System.out.println(i1 == i2);//true
		// 等于 Integer i3 = Integer.valueOf(128);  不过 和 new Integer(128)  没啥区别,因为不符合常量池值的大小,所以是新new
		Integer i3 = 128;
		Integer i4 = 128;
		System.out.println(i3 == i4);//false
		
		// 以下  结果 和 上面结果 相同
		Integer i5 = Integer.valueOf(123);
		Integer i6 = Integer.valueOf(123);
		System.out.println(i5 == i6);//true
		
		Integer i7 = Integer.valueOf(128);
		Integer i8 = Integer.valueOf(128); 
		System.out.println(i7 == i8);//false
		
		// new 的方式  肯定是不行的,因为new了两次,对象内存地址不同,所以 == 比较内存地址,肯定是false,但是 使用equals 一定是true,因为都是1
		Integer i9 = new Integer(1);
		Integer i10 = new Integer(1);
		System.out.println(i9 == i10);//false
		System.out.println(i9.equals(i10));//true
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值