常用API
String
概述
* java.lang.String : 是字符串类 底层就是一个final修饰的char数组,所以String很多特性就是数组的特性,
*
* 比如 一旦确定,长度 不能更改
*
* 1 字符串一旦创建,这个字符串对象不能再更改
*
* 2 为了提升字符串的访问和存储效率,java虚拟机采用了一种缓存机制,把字符串都保存在了字符串常量池中
*
* 3 在程序执行过程中,假如要用到一个字符串a String s1 = "a";先去字符串常量池中检索,是否有a, 如果没有就创建一份
* 假如 有了 String s2 = "a"; 就不再创建,把已有的这个a 返回
*
* 所以 导致 String s1 = "a" String s2 = "a" 此时 使用 s1 == s2 他也是true,因为他们指向同一个字符串对象 就是 a
基本使用
// 第一部分 创建1个对象 ,因为他们都指向常量池
String s1 = "a";
String s2 = "a";
// 比较值 true
System.out.println(s1.equals(s2));
// 比较地址 true
System.out.println(s1 == s2);
// String一旦创建不能更改的意思,并不是这个s1变量不能更改,而是 变量指向的对象中的数据不能更改
s1 = "b";
// 第二部分,如果使用了new的方式,那么会创建堆内存对象,该字符串对象会保存在堆内存中
String s3 = new String("a");
String s4 = new String("a");
// 因为s3和s4不指向常量池,而是分别指向了堆内存,所以地址不同,为false
System.out.println(s3 == s4);
// 但是String中覆写了equals方法,比较值,所以是true
System.out.println(s3.equals(s4));
不要频繁拼接
因为字符串创建之后不能更改,如果频繁拼接的话,效率很低,并且垃圾回收可能也会出现问题
String[] arr = { "a", "b", "c" };
String s1 = "";
for (int i = 0; i < arr.length; i++) {
s1 += arr[i];
}
System.out.println(s1);
构造方法
// 1 字面量
String s1 = "asad";
// 2
String s2 = new String("xxx");
// 3 字节数组
byte[] bytes = { 97, 98, 99, 100, 101, 102 };
String s3 = new String(bytes);
// abcdef
System.out.println(s3);
// 4 字节数组 , 只截取一部分 , 4表示起始下标(包含) , 2 表示个数
String s4 = new String(bytes, 4, 2);
// ef
System.out.println(s4);
// 5 字符数组
char[] chars = { 'a', 'b', 'c', 'd' };
String s5 = new String(chars);
System.out.println(s5);
// 6 字符数组 , 只截取一部分 , 1表示起始下标(包含) , 2 表示个数
String s6 = new String(chars,1,2);
System.out.println(s6);
常用方法
学习API : 1 功能是什么 2 入参和出参是什么 3 怎么用
// 1 char charAt (int index ) : 返回该字符串中,指定位置的字符
String s1 = "qwehihasd";
char c1 = s1.charAt(2);
// e
System.out.println(c1);
// 2 boolean endsWith(String suffix) : 判断该字符串是否以指定字符串结尾
// boolean startsWith(String prefix) : 同上,判断开始
System.out.println("Hello.java".endsWith(".java"));
// 注意空格 , 有空格就匹配不上了
System.out.println("Hello.java".endsWith(".java "));
// 3 boolean equalsIgnoreCase(String str) : 不区分大小写比较两个字符串是否相等
System.out.println("abc".equalsIgnoreCase("aBc"));
// 4 byte[] getBytes() : 把字符串转换为字节数组并返回
byte[] bytes = "abc".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
// 5 char[] toCharArray() : 把字符串转换为字符数组并返回
char[] chars = "abc".toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
// 6 int indexOf(String str) : 获取该字符串中指定字符串的起始索引,找不到返回-1
System.out.println("askdhqwbe".indexOf("kd")); // 2
System.out.println("askdhqwbe".indexOf("kda")); // -1
// 7 int indexOf(String str,int index) :
// 从指定位置开始查找(包含),获取该字符串中指定字符串的起始索引,找不到返回-1
System.out.println("askdhaqwbe".indexOf("a", 5)); // -1
// 8 index lastIndexOf(String str) : 同上,最后一次出现的索引 找不到返回-1
System.out.println("askdhaqwbe".lastIndexOf("a")); // 5
// 9 int length() : 返回该字符串的长度
System.out.println("abc".length());
// 10 String replaceAll(String regex . String replacement);
// 替换指定字符,支持正则表达式
// String replace (String str . String replacement); 不支持正则表达式
// 用1 把 a 替换了并返回新的字符串
// 支持正则表达式,但是没有写正则表达式 是没有区别的
System.out.println("hucgasdqweasd".replaceAll("a", "1"));
System.out.println("hucgasdqweasd".replace("a", "1"));
// 因为 . 在正则表达式中,代表任意字符
System.out.println("qwe.rty.yui.uio".replaceAll(".", ","));
// 可以使用 \ 转义
System.out.println("qwe.rty.yui.uio".replaceAll("\\.", ","));
System.out.println("qwe.rty.yui.uio".replace(".", ","));
// 11 String[] split(String regex) : 分割字符串,返回字符串数组,支持正则表达式,注意 .....
// 点,需要转义
String s2 = "2022.1.14";
String[] arr = s2.split("\\.");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 12 String substring(int begin);获取该字符串中,以某个下标起始的子字符串(包含)
System.out.println("abcdef".substring(2));// cdef
// 13 String substring(int begin, int end) :
// 获取该字符串中,以某个下标起始(包含)到某个下标结束的子字符串(不包含)
System.out.println("abcdef".substring(2, 4));// cd
// 14 String trim() : 去除字符串两边的空格
System.out
.println(" a d sadasd ");
System.out
.println(" a d sadasd "
.trim());
// 15 String toUpperCase() : 转大写
// String toLowerCase() : 转小写
System.out.println("asd".toUpperCase());
// 16 static String valueOf(Object obj) :
// 调用该对象的toString方法,如果为null,则不再调用toString而是返回字符串null
String_05 s = null;
// 打印一个引用类型的时候,会自动调用String的valueOf 所以 会自动调用toString方法
System.out.println(s);
注意
// 1
String a = "a";
String b = "b";
String str = "ab";
// 字面量相加 在编译阶段,就把+去掉了
String d = "a" + "b";
// true
System.out.println(d == str);
// true
System.out.println(d.equals(str));
// 变量相加,因为变量的值是可变的,运算之前没有办法确定变量的值,
// 所以没有办法优化,只能转换为new的方式,重新创建并拼接字符串
String c = a + b;
String e = a + "b";
// false
System.out.println(c == str);
// true
System.out.println(c.equals(str));
// 上面相加 因为变量的值 无法确定 , 如果声明为常量,则可以优化
String str1 = "ab";
final String a1 = "a";
final String b1 = "b";
String c1 = a1+b1;
System.out.println(c1==str1);
// 创建几个对象? 1个
String xx = "a"+"b" +"c"+"d";
StringBuffer和StringBuilder
StringBuffer和StringBuilder : 都是字符串缓冲区,可以做拼接操作\
StringBuffer和StringBuilder和String区别
String : 底层是char数组,定长,一旦创建,不可更改,不合适做字符串拼接操作
StringBuffer和StringBuilder : 底层是char数组,变长,预先在内存中申请一块空间,用来保存很多字符
如果预留空间不够了,会进行自动扩容
默认容量为 16,扩大容量 (当前容量+1)*2 16->34->70
StringBuffer和StringBuilder 的区别
StringBuffer 线程安全,在多线程环境下,不会出现问题
StringBuilder 非线程安全,在多线程环境下,可能会出现问题
public static void main(String[] args) {
// 创建一个对象
StringBuilder sb = new StringBuilder();
String[] arr = {"a","b","c"};
for (int i = 0; i < arr.length; i++) {
// append 就是添加数据,做拼接操作
// 可以链式调用
sb.append(arr[i]).append(",");
}
// 反转
sb.reverse();
// 获取已有元素个数
System.out.println(sb.length());
// 当前容量(数组长度)
System.out.println(sb.capacity());
// toString可以把StringBuilder转换为String类型
String str = sb.toString();
System.out.println(str);
}
包装类
【问】想要对基本类型数据进行更多的操作,怎么办?
【答】最方便的方式就是将其封装成对象。因为在对象描述中就可以定义更多的属性和行为对该基本数据类型进行操作。我们不需要自己去对基本类型进行封装,JDK已经为我们封装好了。
【概念】
1. 装箱就是自动将基本数据类型转换为包装器类型
2. 拆箱就是自动将包装器类型转换为基本数据类型
使用
public static void main(String[] args) {
// 基本类型
byte b1 = 12;
// 封装为包装类
Byte b2 = new Byte(b1);
m1(b2);
long l1 = 123L;
Long l2 = new Long(l1);
}
public static void m1(Object o){
}
// 最大值
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
System.out.println(Long.MAX_VALUE);
System.out.println(Double.MAX_VALUE);
// 创建对象
Integer i1 = new Integer(123);
// 传递字符串也可以,但是必须是纯数字
Integer i2 = new Integer("1231");
// 报错 java.lang.NumberFormatException: For input string: "1231a"
Integer i3 = new Integer("1231a");
// int ---> Integer
Integer i1 = new Integer(123);
i1 = Integer.valueOf(123);
// Integer --> int
int i2 = i1.intValue();
// String --> integer
Integer i3 = new Integer("123");
i3 = Integer.valueOf("123");
// Integer --> String
String string = i3.toString();
// int --> String
String string1 = 123+"";
// String --> int
// 重要 static int parseInt(String str) : 把纯数字的字符串转换为int类型
int i4 = Integer.parseInt("123");
double d1 = Double.parseDouble("2.4");
// 把数字以二进制的字符串形式,并返回
String s1 = Integer.toBinaryString(10);
// 同上,八进制
s1 = Integer.toOctalString(10);
// 同上,十六进制
s1 = Integer.toHexString(10);
System.out.println(s1);
java1.5新特性 自动装箱和自动拆箱
装箱 : 基本类型 到 包装类类型
拆箱 : 包装类类型 到 基本类型
八种包装类 都覆写了 toString 和 equals()方法
// 1.5 之前这么写
Integer i1 = Integer.valueOf(123);
int i2 = i1.intValue();
// 1.5 开始
Integer i3 = 123; // 编译之后 就等于 Integer i3 = Integer.valueOf(123);
int i4 = i3; // 编译之后 就等于 int i4 = i3.intValue();
m1(i3);
// 1234为int类型,会先进行自动装箱为 Integer类型,然后再发生多态转型为Object类型
m1(1234);
常量池
简单来说,常量池就是提前准备好一些对象,当我们要保存数据的时候,发现已经创建好了,就直接拿走,不需要重新创建
总结 :
当我们 通过 new Integer(xx) 创建对象的时候, 不管值是多少,. == 永远是false
当我们使用 Integer i1 = xxx; 这种方式的时候,编译之后 会转换为Integer.valueOf() ; 这种方式会经过整型常量池
假如 xxx这个值 在 -128 到127之间 则 不需要new对象,而是使用常量池中已创建好的对象
否则 不再范围内, 则还是等于 new Integer(xxx) 这种方式
因此
Integer i1 = xxx;
Integer i2 = xxx; 如果 xxx 在-128 ~ 127 之间 则 i1 == i2 是 true
但是 注意 Integer类型之间的比较 还是要用 equals 进行比较才最好
int i = -128;
System.out.println(-i);
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
// false
System.out.println(i1 == i2);
// true
System.out.println(i1.equals(i2));
Integer i3 = Integer.valueOf(-126);
Integer i4 = Integer.valueOf(-126);
// true
System.out.println(i3 == i4);
Integer i5 = 12; // 编译之后 Integer.valueOf(12);
Integer i6 = 12;
// true
System.out.println(i5 == i6);
Integer i7 = 222; // 就等于 new Integer(222)
Integer i8 = 222;
// false , 因为整型常量池的范围在 -128 ~ 127之间
System.out.println(i7 == i8);
system
获取当前毫秒数,计算机时间 System.in用户输入流
//表示错误 以红色字体展示到控制台
System.err.println(123);
//标准输出 --->打印到控制台
System.out.println(123);
//in 表示标准输入 接收控制台输入信息
new Scanner(System.in);
// 获取时间原点到当前时间的毫秒数(1970.1.1 8:0:0)
long startTime = System.currentTimeMillis();
System.out.println("正在执行");
@SuppressWarnings("unused")
long endTime = System.currentTimeMillis();
System.out.println(startTime);
//退出JVM虚拟机 0表示正常关闭 1 表示异常关闭 一般用于图形界面 关闭窗口
System.exit(0);
//执行不到
System.out.println("+=====");
Date
// 获取当前系统时间
Date d1 = new Date();
// 传入毫秒数,获取时间原点到指定毫秒数的世界
Date d2 = new Date(1000);
// Fri Jan 14 16:15:57 CST 2022
System.out.println(d1);
// Thu Jan 01 08:00:01 CST 1970
System.out.println(d2);
// 1642148327849 获取指定时间的毫秒数
System.out.println(d1.getTime());
// 把时间转换为 字符串类型
System.out.println(d1.toString());
/**
* 年 y
* 月 M
* 日 d
* 时 H
* 分 m
* 秒 s
* 毫秒 S
*/
// 创建时间格式化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");
// 格式化,返回字符串
String string = sdf.format(d1);
System.out.println(string);
// 时间格式的字符串 转换为Date对象
String strDate = "2022/01/14 16:21:36";
// 格式化对象的时间格式 要和字符串的格式 一致
sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
// 转换 返回Date对象
Date date = sdf.parse(strDate);
System.out.println(date);
//获取当前日历
Calendar c1 = Calendar.getInstance();
//获取当前是本周第几天,从周日开始
System.out.println(c1.get(Calendar.DAY_OF_WEEK));
//年
System.out.println(c1.get(Calendar.YEAR));
//月
System.out.println(c1.get(Calendar.MONTH)+1);
//日
System.out.println(c1.get(Calendar.DAY_OF_MONTH));
//时 12小时
System.out.println(c1.get(Calendar.HOUR));
//24小时
System.out.println(c1.get(Calendar.HOUR_OF_DAY));
System.out.println(c1.get(Calendar.MINUTE));
System.out.println(c1.get(Calendar.MARCH));
Random
//创建随机数生成器
Random r =new Random();
//在int范围内随机生成一个数字
int i =r.nextInt();
System.out.println(i);
//传入10 说明要在0~9之间生成
i=r.nextInt(10);
System.out.println(i);
//生成10~20
//nextInt(最大值-最小值 + 1 )+ 最小值
int result = r.nextInt(100 - 20 +1)+20;
System.out.println(result);