Java常用类详解
1.包装类
1.1 包装类的分类
-
针对八种基本数据类型相应的引用类型—包装类
-
有了类的特点,就可以调用类中的方法。
-
如图:
1.1.1 包装类和基本数据的转换
- jdk5以前是手动装箱和拆箱方式
- 装箱:基本类型–>包装类型
- 拆箱:包装类型–>基本类型
- jdk5以后(含jdk5)是自动装箱和拆箱方式
- 自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
- 下面用int和Integer演示,其他包装类用法类似:
public static void main(String[] args) {
//演示int <--> Integer 的装箱和拆箱
//其他包装类的用法相似
//jdk5前是手动装箱和拆箱
int n1 = 100;
Integer integer = new Integer(n1);
Integer integer1=Integer.valueOf(n1);
//手动拆箱
//Integer --> int
int i = integer.intValue();
//jdk5以后,就可以自动装箱和自动拆箱
//自动装箱
//底层使用的是 Integer.valueOf(n2)
Integer integer2 = n1;
//自动拆箱
//底层仍然使用的是 Integer.valueOf()方法
int n2 = integer2;
}
-
下面几道简单的代码判断
- 下面的代码是否正确,为什么?
Double d = 100d;//答:正确,自动装箱 Double.valueOf(100d); Float f = 1.5f;//答:正确,自动装箱 Double.valueOf(1.5f);
- 下面两个代码输出结果相同吗?各是什么?
//代码1: Object obj1 = true?new Integer(1):new Double(2.0); //三元运算符 [是一个整体] //所以输出的结果是 1.0 System.out.println(obj1); //代码2: Object obj2; if (true) obj2 = new Integer(1); else obj2 = new Double(2.0); //输出的结果为 1 System.out.println(obj2);
1.1.2 包装类型和String 类型的相互转换
- 这里以 Integer 和 String 转换为例,其它的类似:
public static void main(String[] args) {
//包装类(Integer) -> String
Integer i = 100;//自动装箱
//方式一
String str1 = i+"";
//方式二
String str2 = i.toString();
//方式三
String str3 = String.valueOf(i);
//String -> 包装类(Integer)
String str4 = "123";
//方式一
int i2 = Integer.parseInt(str4);
//方式二
Integer i3 = new Integer(str4);
}
-
Integer和Character有些常用的方法
这里只是列举了一点点常用的方法,还有非常多的方法:
public static void main(String[] args) {
System.out.println(Integer.MIN_VALUE); //返回最小值
System.out.println(Integer.MAX_VALUE);//返回最大值
System.out.println(Character.isDigit('a'));//判断是不是数字
System.out.println(Character.isLetter('a'));//判断是不是字母
System.out.println(Character.isUpperCase('a'));//判断是不是大写
System.out.println(Character.isLowerCase('a'));//判断是不是小写
System.out.println(Character.isWhitespace('a'));//判断是不是空格
System.out.println(Character.toUpperCase('a'));//转成大写
System.out.println(Character.toLowerCase('A'));//转成小写
}
1.1.3 Integer 类面试题 1
- 看下面代码,输出什么结果?为什么?
public static void main(String[] args) {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//false
/*看源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
源码解读:
1. 如果 i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回
2. 如果不在 -128~127,就直接 new Integer(i)
*/
//所以,这里主要是看范围 -128 ~ 127 就是直接返回
Integer m = 1;//底层 Integer.valueOf(1)
Integer n = 1;//底层 Integer.valueOf(1)
System.out.println(m == n);//true
//128不在 -128~127,就直接 new Integer(i)
Integer x = 128;//底层 Integer.valueOf(1)
Integer y = 128;//底层 Integer.valueOf(1)
System.out.println(x == y);//false
}
1.1.4 Integer 类面试题总结
- 看看下面代码,输出什么结果.
public static void main(String[] args) {
//实例一
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);//false
//实例二
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4);//false
//实例三
Integer i5 = 127;
Integer i6 = 127;
System.out.println(i5 == i6);//true
//实例四
Integer i7 = 128;
Integer i8 = 128;
System.out.println(i7 == i8);//false
//实例五
Integer i9 = 127; //Integer.valueOf(127)
Integer i10 = new Integer(127);
System.out.println(i9 == i10);//false
//实例六
Integer i11 = 127;//Integer.valueOf(127)
int i12 = 127;
//只要有基本数据类型,判断的是值是否相等
System.out.println(i11 == i12);//true
//实例七
Integer i13 = 128;
int i14 = 128;
//只要有基本数据类型,判断的是值是否相等
System.out.println(i13 == i14);//true
}
2. String类
2.1 String类的理解和创建对象
2.1.1 String类的理解
-
String对象是用保存字符串的,也就是一组字符串序列
-
字符串常量对象是用双引号括起的字符序列。
- 例如:“你好”、“hello”、"123"等
-
字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
-
String类有很多的构造器,实现了构造器的重载
- 下面几个是较常用的构造器(看其他手册)
String s1 = new String();//
String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int starIndex,int count);
String s5 = new String(byte[] b)
- 代码
public static void main(String01[] args) {
//1.String对象是用保存字符串的,也就是一组字符串序列
//2."jack" 字符串常量,用双引号括起的字符序列
//3.字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
//4.String 类有很多构造器,实现了构造器的重载
/*较常用的构造器
1.String s1 = new String();//
2.String s2 = new String(String original);
3.String s3 = new String(char[] a);
4.String s4 = new String(char[] a,int starIndex,int count);
5.String s5 = new String(byte[] b)
*/
//5.String类实现了接口 Serializable[String 可以串行化;可以在网络传输]
// Comparable [String 对象可以比较大小]
//6.String 是final类,不能被其它类继承
//7.String 有属性 private final char value[];用于存放字符串内容
// The value is used for character storage;
//8.一定要注意: value 是 final类型,不可以修改(地址);
// 即value不能指向新的地址,但是单个字符内容是可以变化的
String name = "jack";
name = "Lucy";
final char[] value = {'a','b','c'};
value[0] = '5';//单个字符可以变化
char[] v2 = {'1','2','3'};
//value = v2; 不可以修改value的地址
}
2.1.2 创建String对象的两种方式
-
方式一:直接赋值 String S = “sys”;
-
方式二:调用构造器 String s = new String(“sys”);
-
区别:
- 方式一:先从常量池查看是否有"sys"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。S最终指向的是常量池的空间地址。
- 方式二:先在堆中创建空间,里面维护了value属性,指向常量池的"sys"空间,如果常量池没有"sys",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
-
测试题
-
- 判断下面代码输出结果
public static void main(String[] args) { String a = "abc"; String b = "abc"; System.out.println(a.equals(b));//true System.out.println(a == b);//true }
-
- 判断下面代码输出结果
public static void main(String[] args) { String a = new String("abc"); String b = new String("abc"); System.out.println(a.equals(b));//true System.out.println(a == b);//false }
-
- 判断下面代码输出结果
public static void main(String[] args) { String a = "abc";//a指向常量池 String b = new String("abc");//b指向堆中对象 System.out.println(a.equals(b));//true System.out.println(a == b);//false System.out.println(a == b.intern());//true System.out.println(b == b.intern());//false /* 当调用intern方法时,如果池里已经包含一个等于此String对象的字符串(用equals(Object)方法确定), 则返回来自池的字符串。 否则,将此String对象添加到池中,并返回此String对象的引用。 解读:(1)b.intern()方法最终返回的是常量池的地址(对象)。 */ }
-
- 判断下面代码输出结果
public static void main(String[] args) { String s1 = "sys"; String s2 = "java"; String s4 = "java"; String s3 = new String("java"); System.out.println(s2 == s3);//false System.out.println(s2 == s4);//true System.out.println(s2.equals(s3));//true System.out.println(s1 == s2);//false }
-
- 判断下面代码输出结果
public static void main(String[] args) { Person p1 = new Person(); p1.name = "sys"; Person p2 = new Person(); p2.name = "sys"; System.out.println(p1.name.equals(p2.name));//比较内容:true System.out.println(p1.name == p2.name);//true System.out.println(p1.name == "sys");//true String s1 = new String("abcd"); String s2 = new String("abcd"); System.out.println(s1 == s2);//false }
-
3. 字符串的特性
-
判断下面代码创建了几个对象
- 练习1:
public static void main(String[] args) { //1.String 是一个final类,代表不可变的字符序列 //2.字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的 //以下语句创建了几个对象? String s1 = "hello";//s1指向常量池里面的"hello" //此时常量池里面没有"haha",重新创建一个"haha" // 然后s1指向常量池里面的"haha" // 所以一共创建了两个对象 s1 = "haha"; }
- 练习2:
public static void main(String[] args) { //题1:下面代码创建了几个对象? String a = "hello"+"abc"; //代码解读 //原先代码: String a = "hello"+"abc"; //编译器会做一个优化,判断创建的常量池对象,是否有引用指向 //直接把代码优化为: String a = "helloabc"; //所以只有一个对象 //题2:下面代码创建了几个对象? String b = "hello";//创建了b对象 String c = "abc";//创建了c对象 String d = b+c; //关键是分析 String d = b+c;到底是怎么执行的 //代码解读 String d = b+c; //1.底层先创建一个StringBuilder (Stringbuilder sb = StringBuilder) //2.然后执行sb.append("hello"); //3.接着执行sb.append("abc"); // sb在堆中,并且append是在原来字符串的基础上追加的 //4.String c = sb.toString(); //最后其实是 c 指向堆中的对象(String)value[]-->池中"helloabc" //所以一共有三个对象 //重要规则 //String a = "hello"+"abc"; 常量相加,看的是池 //String d = b+c; 变量相加,是在堆中; }
-
下面代码的运行结果是什么?
-
- 下面代码输出什么,请说明原因
public static void main(String[] args) { //下面代码输出什么 String s1 = "sys";//s1指向池中的"sys" String s2 = "java";//s2指向池中的"java" String s3 = "sysjava";//s3指向池中的"sysjava" String s4 = (s1+s2).intern();//s4指向池中的"sysjava" System.out.println(s3==s4);//true System.out.println(s3.equals(s4));//true }
-
- 下面程序运行的结果是什么?
public static void main(String[] args) { Test1 ex = new Test1(); ex.change(ex.str, ex.ch); System.out.println(ex.str+"and");//输出sysand System.out.println(ex.ch);//输出hava } class Test1{ String str = new String("sys"); final char[] ch = {'j','a','v','a'}; public void change(String str,char ch[]){ str = "java"; ch[0] = 'h'; } }
-
4. String类的常见方法
4.1 说明
- String类是保存字符串常量的。每次更新都需要重新开辟空间,效率极低,因此java设计者还提供了StringBuilder和StringBuffer来增强String的功能,并提高效率。[初步了解]
//例如这段代码
String s = new String("");
for(int i = 0,i <10000,i++){
s+="hello";
}
4.2 String类的常见方法1[了解]
- equals //区分大小写,判断内容是否相等
- equalslgnoreCase //忽略大小写的判断内容是否相等
- length //获取字符的个数,字符串的长度
- indexOf //获取字符在字符串中第1次出现的索引 (索引从0开始。如果找不到,就返回-1)
- lastIndexOf //获取字符在字符串中最后1次出现的索引 (索引从0开始。如果找不到,就返回-1)
- substring //截取指定范围的子串
- trim //去前后空格
- charAt //获取某索引处的字符,注意不能使用 Str[index] 这种方式
public static void main(String[] args) {
//1. equals //区分大小写,判断内容是否相等
String str1 = "hello";
String str2 = "Hello";
System.out.println(str1.equals(str2));//false
//2. equalslgnoreCase //忽略大小写的判断内容是否相等
String str3 = "Jack";
if ("jack".equalsIgnoreCase(str3)) {
System.out.println("ok");
} else {
System.out.println("no");
}//输出ok
//3. length //获取字符的个数,字符串的长度
String str4 = "sys";
System.out.println(str4.length());//3
//4. indexOf //获取字符在字符串中第1次出现的索引 (索引从0开始。如果找不到,就返回-1)
String str5 = "sys@java@study";
int index = str5.indexOf('@');
System.out.println(index);//3
System.out.println("sys="+str5.indexOf("sys"));//0
//5. lastIndexOf //获取字符在字符串中最后1次出现的索引 (索引从0开始。如果找不到,就返回-1)
int index2 = str5.lastIndexOf("@");
System.out.println(index2);//8
System.out.println("java="+str5.lastIndexOf("java"));//4
//6. substring //截取指定范围的子串
String name = "hello,jack";
System.out.println(name.substring(6));//从索引6开始截取后面的所有内容
System.out.println(name.substring(0,5));//表示从索引0开始,截取到索引 5-1 = 4的字符
//7. trim //去前后空格
//8. charAt //获取某索引处的字符,注意不能使用 Str[index] 这种方式
}
4.3 String类的常见方法应用实例2[了解]
- toUpperCase //转换成大写
- toLowerCase //转换成小写
- concat //拼接字符
- replace //替换字符串中的字符
- split //分割字符串,对于某些分割字符,我们需要转义 比如 | \ \deng
- compareTo //比较两个字符串的大小
- toCharArray //转换成字符数组
- format //格式化字符串,%s 字符串, %c 字符, %d 整型, %.2f 浮点型,
public static void main(String[] args) {
//1. toUpperCase //转换成大写
String str1 = "jack";
System.out.println(str1.toUpperCase());//JACK
//2. toLowerCase //转换成小写
String str2 = "JAVA";
System.out.println(str2.toLowerCase());//java
//3. concat //拼接字符
String str3 = "sys";
str3 = str3.concat("学").concat("学").concat("java");
System.out.println(str3);//sys 学 学 java
//4. replace //替换字符串中的字符
// str3.replace() 方法执行后,返回的结果才是替换过的
// 注意:对 str3 没有任何影响
String str4 = str3.replace("学","study");//将所有的 学 替换成 study
System.out.println(str3);//sys 学 学 java
System.out.println(str4);//sys study study java
//5. split //分割字符串,对于某些分割字符,我们需要转义 比如 | \\ \deng
String poem = "大家好,我是,sys,学,java";
// 以 , 为标准对 poem进行分割,返回一个数组
String[] poem1 = poem.split(",");
for (int i = 0; i < poem1.length; i++) {
System.out.println(poem1[i]);
}
poem = "D:\\aaa\\bbb\\ccc";
// 在对字符串进行分割时,如有特殊字符,需要加入 转义符 \
poem1 = poem.split("\\\\");
for (int i = 0; i < poem1.length; i++) {
System.out.println(poem1[i]);
}
//6. compareTo //比较两个字符串的大小
// 如果前者大,则返回正数
// 如果后者大,则返回负数
// 如果两者相等,则返回0
String a = "jack";
String b = "jack";
String c = "lucy";
//如何比较
//1.如果长度相等,并且每个字符也相同,就返回0
//2.如果长度或字符不相等,在进行比较时,可以区分大小写
// if (c1 != c2) {
// return c1 - c2;
// }
//3.如果长度不同,如果前面的部分都相同,就返回str1.length - str2.length
System.out.println(a.compareTo(b));//0
System.out.println(a.compareTo(c));//-2
//7. toCharArray //转换成字符数组
String s = "imformation";
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
System.out.println(ch[i]);
}
//8. format //格式化字符串,%s 字符串, %c 字符, %d 整型, %.2f 浮点型,
String name = "sys";
int age = 28;
double score = 88.8;
char gender = '男';
String info =
"我的名字是"+name+"年龄是"+age+"成绩是"+score+"性别是"+gender+"很高兴认识大家";
System.out.println(info);
//%s , %c , %d , %.2f 称为占位符;
//这些占位符由后面变量来替换
//%s 表示后面用 字符串 来替换
// %c 表示后面由 字符 来替换
// %d 表示后面由 整数 来替换
// %.2f 表示后面由 浮点数 来替换 2f表示保留2位小数[四舍五入]
//写法1:
String info2 = String.format("我的名字是%s 年龄是%d 成绩是%.2f 性别是%c 很高兴认识大 家",name,age,score,gender);
System.out.println(info2);
//写法2:
String formatStr = "我的名字是%s 年龄是%d 成绩是%.2f 性别是%c 很高兴认识大家";
String info3 = String.format(formatStr,name,age,score,gender);
System.out.println(info3);
}
5. StringBuffer 类
5.1 基本介绍
- java.lang.StringBuffer 代表可变的字符序列,可以对字符串进行增删;
- StringBuffer的很多方法和String相同,但StringBuffer是可变长度的;
- StringBuffer 的直接父类 是 AbstractStringBuilder;
- StringBuffer 实现了 Serializable, 即StringBuffer的对象可以串行化;
- 在父类中 AbstractStringBuilder 有属性 char[] value,不是final
- 该 value 数组存放 字符串内容,引出存放在堆中的
- SringBuffer 是一个final类,不能被继承
- 因为StringBuffer字符内容是存在 char[] value,所以在变化(增加/删除) ,不用每次都更换地址(即创建新对象),所以效率高于String
5.2 String VS StringBuffer
- String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率极低。//private final char value[];
- StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率极高。//char[] value 放在堆中
5.3 StringBuffer的构造器
- StringBuffer()
- 构造一个没有字符的字符串缓冲区,初始容量为16个字符。
- StringBuffer(CharSequence seq)
- 构造一个包含与指定的相同字符的字符串缓冲区 CharSequence 。
- StringBuffer(int capacity)
- 构造一个没有字符的字符串缓冲区和指定的初始容量。
- StringBuffer(String str)
- 构造一个初始化为指定字符串内容的字符串缓冲区。
public static void main(String[] args) {
//StringBuffer 构造器的使用:
// 1.创建一个 大小为 16 的char[] ,用于存放字符内容
StringBuffer stringBuffer = new StringBuffer();
//2.构造一个包含与指定的相同字符的字符串缓冲区 CharSequence 。
//StringBuffer(CharSequence seq)
//3.通过构造器指定 char[] 大小
StringBuffer stringBuffer1 = new StringBuffer(100);
//4.通过 给一个String 创建StringBuffer , char[]大小就是 str.length()+16
StringBuffer stringBuffer2 = new StringBuffer("hello");
}
5.4 String和StringBuffer相互转换
- 在开发中,我们经常需要将String和StringBuffer进行转换
- 看如下代码
public static void main(String[] args) {
//看 String --> StringBuffer
String s = "hello";
//方式 1 使用构造器
//注意: 返回的才是 StringBuffer 对象,对 str 本身没有影响
StringBuffer stringBuffer = new StringBuffer(s);
//方式二:使用的是 append 方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(s);
//看 StringBuffer --> String
StringBuffer stringBuffer2 = new StringBuffer("sys");
//方式一:使用 StringBuffer 提供的 toString 方法
String s2 = stringBuffer2.toString();
//方式二:使用构造器来搞定
String s3 = new String(stringBuffer2);
}
5.5 StringBuffer类常见方法
- 增append
- 删delete(start,end)
- 改replace(start,end,string)
- 将start—end间的内容换掉,不含end
- 查indexOf
- 查找子串在字符串第一次出现的索引,如果找不到返回-1
- 插insert
- 获取长度length
- 代码操作:
public static void main(String[] args) {
//增 append
StringBuffer stringBuffer = new StringBuffer("sys");
stringBuffer.append("学");//sys学
stringBuffer.append("100");//sys学100
stringBuffer.append("java");//sys学100java
System.out.println(stringBuffer);
//删 delete
/*
删除索引为>=start && < end处的字符
解读:删除 4~7处的字符 [4,7)
*/
stringBuffer.delete(4,7);//删除4-6位置的字符
System.out.println(stringBuffer);//sys学java
//改 replace
//将start---end间的内容换掉,不含end
//使用 study 替换掉 索引3-4的字符[3,4)
stringBuffer.replace(3,4," study ");
System.out.println(stringBuffer);//sys study java
//查 indexOf
//查找指定的子串在字符串第一次出现的索引,如果找不到就返回-1
int index = stringBuffer.indexOf("study");
System.out.println(index);//4
//插入 inert
//在索引9的位置插入100
stringBuffer.insert(9,"100");
System.out.println(stringBuffer);//sys study100 java
//长度 length
System.out.println(stringBuffer.length());//17
}
5.6 StringBuffer 练习题
- 看下面代码输出什么?为什么
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);//需要看源码
//底层调用的是AbstractStringBuilder的 appendNull()
//直接把空转为一个字符串{'n','u','l','l'}
System.out.println(sb.length());//字符串的长度为4
System.out.println(sb);//null
//看底层源码
StringBuffer sb1 = new StringBuffer(str);
/*
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
*/
//这里会变成 null.length() + 16
//这里构造器会直接抛出空指针异常
// NullPointerException
System.out.println(sb1);
}
- 按照要求编写代码:
public static void main(String[] args) {
//输入商品名称和价格,要求打印效果示例,
// 使用前面学习的方法完成:
/*
商品名 商品价格
手机 123,561,531,564.59
*/
//要求:价格的小数点前面每三位用小数点隔开
String a = "商品名";
String price = "123561531564.59";
StringBuffer sb = new StringBuffer(a);
StringBuffer sb2 = new StringBuffer(price);
//增加"商品价格" 补齐抬头
sb = sb.append("\t商品价格");
//先完成一个最简单的实现123564.59
//找到小数点的索引 ,然后再该位置的前3位插入 , 即可
/*初始操作
int index = sb2.indexOf(".");
sb2.insert(index-3,",");
*/
//万一数字不止那么多,上面两步只插入了一个 ,
// 上面两步需要做一个循环处理
//循环方法1:
/*
int index = sb2.indexOf(".");
for (int i = index; i >3; i-=3) {
sb2 = sb2.insert(index-3,",");
index-=3;
}
*/
//循环方法2:把代码合并为一个代码
for (int i = sb2.indexOf(".")-3; i > 0 ; i-=3) {
sb2 = sb2.insert(i,",");
}
//前面插入 "手机"
sb2.insert(0,"手机\t");
System.out.println(sb);
System.out.println(sb2);
}
6.StringBuilder类
6.1 基本介绍
- StringBuilder 是一个可变的字符序列。
- 此类提供一个与StringBuffer 兼容的API,但不保证同步。(StringBuilder 不是线程安全的)
- 该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候。
- 如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快。
- 在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接收任意类型的数据。
6.2 结构剖析
- StringBuilder 继承了 AbstractStringBuilder 类;
- 实现了 Serializable ,说明StringBuilder对象是可以串行化(对象可以网络传输,可以保存到文件);
- StringBuilder 是final类,不能被继承;
- StringBuilder 对象字符序列仍然是存放在其父类AbstractStringBuilder的char[] value中,因此,字符序列是在堆中;
- StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用StringBuilder;
6.3 String、StringBuffer和StringBuilder的比较
- StringBuilder 和StringBuffer 非常相似,均可代表可变的字符序列,而且方法也一样;
- String:不可改变字符序列,效率低,但是复用率高;
- StringBuffer:可改变字符序列、效率较高(增删)、线程安全(看源码,方法都有synchronized关键字);
- StringBuilder:可改变字符序列,效率最高、线程不安全;
- String使用注意说明:
- String s = “a”;//创建了一个字符串
- s += “b”;//实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符对象留在内存中,降低效率。如果这样的操作放在循环中,会极大影响程序的性能;
- 结论:如果我们对String做大量修改,不要使用String;
6.4 String、StringBuffer和StringBuilder的效率测试
- 测试代码如下:
public static void main(String[] args) {
//设置初始时间和结束时间清零
long startTime = 0L;
long endTime = 0L;
//StringBuffer
StringBuffer buffer = new StringBuffer("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间为" + (endTime - startTime));//32ms
//StringBuilder
StringBuilder builder = new StringBuilder("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的运行时间为" + (endTime - startTime));//15ms
//String
String test = "";
startTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {
test = test + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的运行时间为" + (endTime - startTime));//17614ms
}
- 由上面的代码测试可得效率:
- StringBuilder > StringBuffer > String
6.5 String、StringBuffer和StringBuilder的选择
使用的原则,结论:
- 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder
- 如果字符串存在大量的修改操作,并在单线程的情况下,使用StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况下,使用StringBuffer
- 如果我们字符串很少修改,被多个对象引用,使用String。
- 比如配置信息等
- StringBuilder和StingBuffer的方法一样。
7. Math类
7.1. 基本介绍
- Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
7.2. Math方法一览(均为静态方法)
- abs 绝对值
- pow 求幂
- ceil 向上取整,返回 >= 该参数的最小整数
- floor 向下取整,返回 <= 该参数的最大整数
- round 四舍五入 相当于Math.floor(该参数+0.5)
- sqrt 求开方
- random 求随机数
- max min 最大值和最小值
- 下面进行简单的代码操作:
public static void main(String[] args) {
//Math的静态方法
//1.abs 绝对值
int abs = Math.abs(-3);
System.out.println(abs);//3
//2.pow 求幂
double pow = Math.pow(2, 3);//2的3次方
System.out.println(pow);//8.0
//3.ceil 向上取整,返回 >= 该参数的最小整数
double ceil = Math.ceil(5.2);
System.out.println(ceil);//6.0
//4.floor 向下取整,返回 <= 该参数的最大整数
double floor = Math.floor(2.9);
System.out.println(floor);//2.0
//5.round 四舍五入 相当于Math.floor(该参数+0.5)
double round = Math.round(5.49);
System.out.println(round);//5.0
//6.sqrt 求开方
double sqrt = Math.sqrt(9);
System.out.println(sqrt);//3.0
//7.random 求随机数
//思考:请写出获取 a-b 之间的一个随机整数,
// a,b均为正数 2-7
//解题思路:
//(1) random 返回的是 0 <= x <1 之间的一个随机小数
//(2) Math.random()*(b-a) 返回的是 0 <= x <(b-a)的随机小数
//(3) (int)(a+Math.random()*(b-a+1)) 返回的就是 a <= x <b-a+1的随机整数
// 现在要取2-7之间的整数,那么就是(int)(2+Math.random()*(7-2+1))
// Math.random()*6 返回的是 0 <= x < 6
// 2+Math.random()*6 返回的是 2 <= x < 8
// 那么(int)(2+Math.random()*6) 返回的就是2-7之间的随机整数
//(4) 公式就是(int)(a+Math.random()*(b-a+1))
int random = (int) (2 + Math.random() * 6);
for (int i = 0; i < 10; i++) {
System.out.println(random);//输出2-7之间的随机整数
}
//8.max min 最大值和最小值
int min = Math.min(21, 66);
int max = Math.max(21, 66);
System.out.println(min);//21
System.out.println(max);//66
}
8.Arrays类
8.1 Arrays类常见方法应用案例
-
Arrays里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)。
- ① toString 返回数组的字符串形式 Arrays.toString(arr)
public static void main(String[] args) { Integer[] integers = {1, 2, 5, 15}; /* //以前遍历数组 for (int i = 0; i < integers.length; i++) { System.out.println(integers[i]); } */ //toString 返回数组的字符串形式 System.out.println(Arrays.toString(integers));//[1, 2, 5, 15] }
- ② sort 排序(自然排序和定制排序) Integer arr[] = {-5, 1, -10, 7, 0, 18, 9};
public static void main(String[] args) { //sort 排序(自然排序和定制排序) //1. 可以直接使用冒泡排序 , 也可以直接使用 Arrays 提供的 sort 方法排序 //2. 因为数组是引用类型,所以通过 sort 排序后,会直接影响到 实参 arr //3. sort 重载的,也可以通过传入一个接口 Comparator 实现定制排序 //4. 调用 定制排序 时,传入两个参数 /* (1) 排序的数组 arr (2) 实现了 Comparator 接口的匿名内部类 , 要求实现 compare 方法 */ //5.这里体现了接口编程的方式 , 看看源码,就明白 // 源码分析 //(1) Arrays.sort(arr, new Comparator() //(2) 最终到 TimSort 类的 // private static <T> void binarySort(T[] a, int lo, int hi, int start,Comparator<? super T> c)() //(3) 执行到 binarySort 方法的代码, 会根据动态绑定机制 c.compare() // 执行我们传入的匿名内部类的 compare () /* while (left < right) { int mid = (left + right) >>> 1; if (c.compare(pivot, a[mid]) < 0) right = mid; else left = mid + 1; } */ /*(4) new Comparator() { @Override public int compare(Object o1, Object o2) { Integer i1 = (Integer) o1; Integer i2 = (Integer) o2; return i2 - i1; } } */ //(5) public int compare(Object o1, Object o2) 返回的值>0 还是 <0 // 会影响整个排序结果, 这就充分体现了 接口编程+动态绑定+匿名内部类的综合使用 // 底层框架和源码的使用方式,会非常常见 Integer arr[] = {-5, 1, -10, 7, 0, 18, 9}; //自然排序 //Arrays.sort(arr); // 默认排序方法 /* Arrays.sort(arr);//[-10, -5, 0, 1, 7, 9, 18] */ //定制排序 Arrays.sort(arr, new Comparator() { @Override public int compare(Object o1, Object o2) { Integer i1 = (Integer) o1; Integer i2 = (Integer) o2; return i2 - i1;// [18, 9, 7, 1, 0, -5, -10] //return i1-i2;// [-10, -5, 0, 1, 7, 9, 18] } }); System.out.println(Arrays.toString(arr)); }
- 上面提到的sort定制排序,我们可以自己通过原理冒泡排序去编一个定制排序的代码,能更好的理解
public static void main(String[] args) { int[] arr = {1,-1,8,2}; //bubble(arr);//冒泡排序 bubble02(arr, new Comparator() { @Override public int compare(Object o1,Object o2) { int i1 = (Integer)o1; int i2 = (Integer)o2; //return i1 - i2;// [-1, 1, 2, 8] return i2 - i1;// [8, 2, 1, -1] } }); System.out.println(Arrays.toString(arr)); } //冒泡排序 public static void bubble(int[] arr){ int temp = 0; for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-1-i; j++) { if (arr[j]>arr[j+1]){ temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } //定制排序 public static void bubble02(int[] arr,Comparator c){ int temp = 0; for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-1-i; j++) { //数组排序由 c.compareTo(arr[j],arr[j+1]) 返回的值决定 if (c.compare(arr[j],arr[j+1])>0){ temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } }
- ③ binarySearch 通过二分搜索法进行查找,要求必须排好序 int index = Arrays.binarySearch(arr,3);
public static void main(String[] args) { //binarySearch 通过二分搜索法进行查找,要求必须排好序 Integer[] arr = {1,3,5,8,12,25}; //1.使用binarySearch 二叉查找 //2.要求该数组是有序的,如果该数组无序,那么不能使用binarySearch //3.如果该数组不存在该元素,那么返回 return -(low + 1); // key not found. // low 代表数组在的位置 int index = Arrays.binarySearch(arr,5); System.out.println("index = "+index);//输出2 //找不到的情况下 //如果 9 存在的话应该在8后面,那么下标应该为 4 //现在不存在 9,所以index = -(4+1) = -5 int index2 = Arrays.binarySearch(arr,9); System.out.println("index2 = "+index2);//输出-5 }
- ④ copyOf 数组元素的复制 Integer[] newArr = Arrays.copyOf(arr,arr.length);
public static void main(String[] args) { Integer[] arr = {1, 3, 5, 8, 25}; //copyOf 数组元素的复制 Integer[] newArr = Arrays.copyOf(arr,arr.length); //1.从 arr 数组中,拷贝 arr.length 个元素到新数组 newArr 中 //2.如果拷贝的长度 > arr.length 就在新数组后面加一个 null //3.如果拷贝长度 < arr.length 就从数组 arr 最后面往前删除数组元素 // 当拷贝长度 < 0时,就会抛出异常 NegativeArraySizeException //4.该方法使用的底层源码是 System.arraycopy() //完全拷贝 //1.从 arr 数组中,拷贝 arr.length 个元素到新数组 newArr 中 Integer[] newArr = Arrays.copyOf(arr, arr.length); System.out.println("===拷贝执行完后==="); System.out.println(Arrays.toString(newArr));//[1, 3, 5, 8, 25] //增加拷贝数组长度 //2.如果拷贝的长度 > arr.length 就在新数组后面加一个 null Integer[] newArr2 = Arrays.copyOf(arr, arr.length + 1); System.out.println(Arrays.toString(newArr2));//[1, 3, 5, 8, 25, null] //减少拷贝数组长度 //3.如果拷贝长度 < arr.length 就从数组 arr 最后面往前删除数组元素 // 当拷贝长度 < 0时,就会抛出异常 NegativeArraySizeException Integer[] newArr3 = Arrays.copyOf(arr, arr.length - 1); System.out.println(Arrays.toString(newArr3));//[1, 3, 5, 8] //当拷贝长度 < 0时 Integer[] newArr4 = Arrays.copyOf(arr, arr.length - 6); //抛出异常 NegativeArraySizeException System.out.println(Arrays.toString(newArr4)); }
- ⑤ fill 数组元素的填充
- ⑥ equals 比较两个数组元素内容是否完全一致
- ⑦ asList 将一组值,转换成 list
- 代码剖析:
public static void main(String[] args) { Integer[] arr = {1, 3, 5}; //fill 数组元素的填充 //使用 6 去填充 arr 数组,可以理解为6替换原数组中所有的元素 Arrays.fill(arr, 6); System.out.println(Arrays.toString(arr));//[6, 6, 6] //equals 比较两个数组元素内容是否完全一致 //1.如果两个数组中的元素完全一样,则返回true //2.如果两个数组中的元素不是完全一样,则返回false Integer[] arr2 = {1, 3, 5}; Integer[] arr3 = {1, 3, 5, 7}; boolean equals = Arrays.equals(arr, arr2); boolean equals2 = Arrays.equals(arr, arr3); System.out.println("equals = " + equals);//true System.out.println("quals2 = " + equals2);//false // asList 将一组值,转换成 list //1.asList 方法,会将(1,3,5,7)的数据转成一个List集合 //2.返回的是 asList 编译类型 List(接口) //3.asList 运行类型 java.util.Arrays$ArrayList // 是Arrays里面的静态内部类 // private static class ArrayList<E> extends AbstractList<E> // implements RandomAccess, java.io.Serializable List asList = Arrays.asList(1, 3, 5, 7); System.out.println("asList = " + asList); System.out.println("asList的运行类型" + asList.getClass()); }
8.2 Arrays类小练习
-
案例:自定义 Book 类,里面包含 name 和 price,按 price 排序(从大到小)。
-
要求:
- 使用两种方式排序 , 有一个 Book[] books = 4 本书对象.
- 使用前面学习过的传递 实现 Comparator 接口匿名内部类,也称为定制排序。
- 可以按照 price (1)从大到小 (2)从小到大 (3) 按照书名长度从大到小
- 代码如下:
public static void main(String[] args) { //1. 案例:自定义 Book 类,里面包含 name 和 price,按 price 排序(从大到小)。 //2. 要求: // 使用两种方式排序 , 有一个 Book[] books = 4 本书对象. // 使用前面学习过的传递 实现 Comparator 接口匿名内部类,也称为定制排序。 // 可以按照 price (1)从大到小 (2)从小到大 (3) 按照书名长度从大到小 Book[] books = new Book[4]; books[0] = new Book("西游记", 66); books[1] = new Book("三国演义", 68); books[2] = new Book("金瓶梅新版", 88); books[3] = new Book("新少林寺传奇", 99); /* //(1) 从大到小 Arrays.sort(books, new Comparator() { //这里是对Book数组排序,因此o1 和o2就是Book对象 @Override public int compare(Object o1, Object o2) { Book books1 = (Book)o1; Book books2 = (Book)o2; int priceVal = books1.getPrice()-books2.getPrice(); //进行转换 if (priceVal>0){ return -1; } else if (priceVal<0) { return 1; }else { return 0; } } }); */ /* //(2) 从小到大 Arrays.sort(books, new Comparator() { //这里是对Book数组排序,因此o1 和o2就是Book对象 @Override public int compare(Object o1, Object o2) { Book books1 = (Book)o1; Book books2 = (Book)o2; int priceVal = books1.getPrice()-books2.getPrice(); //进行转换 if (priceVal>0){ return 1; } else if (priceVal<0) { return -1; }else { return 0; } } }); */ //(3) 按照书名长度从大到小 Arrays.sort(books, new Comparator() { //这里是对Book数组排序,因此o1 和o2就是Book对象 @Override public int compare(Object o1, Object o2) { Book books1 = (Book) o1; Book books2 = (Book) o2; return books2.getName().length() - books1.getName().length(); } }); System.out.println(Arrays.toString(books)); } } //创建 Book 类,里面包含 name 和 price class Book { private String name; private int price; //构造器 public Book(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } //子类重写toString方法 @Override public String toString() { return "books{" + "name='" + name + '\'' + ", price=" + price + '}'; } }
9. System类
9.1 System类常见的方法和案例
- exit 退出当前程序
- arraycopy:复制数组元素,比较适合底层调用,一般使用 Arrays.copyOf 完成复制数组
- currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
- gc:运行垃圾回收机制 System.gc();
- 代码剖析:
public static void main(String[] args) {
/*
//1. exit 退出当前程序
System.out.println("s1");//输出s1
//1. exit(0) 表示程序退出
//2. 0表示一个状态,正常的状态
System.exit(0);
System.out.println("s2");//输出不了s2
*/
/*
//2. arraycopy:复制数组元素,比较适合底层调用,
// 一般使用 Arrays.copyOf 完成复制数组
int[] src = {1,2,3};
int[] dest = new int[3];
// src: 源数组
// src – the source array.
// srcPos: 从源数组的哪个索引位置开始
// srcPos – starting position in the source array.
// dest: 目标数组,即把源数组的数组拷贝到哪个数组
// dest – the destination array.
// destPos: 把源数组的数据拷贝到 目标数组的哪个索引
// destPos – starting position in the destination data.
// length: 从源数组拷贝多少个数据到目标数组
// length – the number of array elements to be copied.
//从源数组 src 索引为0的位置开始 拷贝到目标数组 dest 索引为0的位置,拷贝3个数据
System.arraycopy(src,0,dest,0,3);
System.out.println(Arrays.toString(dest));//[1, 2, 3]
//从源数组 src 索引为1的位置开始 拷贝到目标数组 dest 索引为1的位置,拷贝2个数据
System.arraycopy(src,1,dest,1,2);
System.out.println("dest="+Arrays.toString(dest));//[0,2,3]
*/
//currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
System.out.println(System.currentTimeMillis());
}
10. BigInteger和BigDecimal类
10.1 BigInteger和BigDecimal介绍
应用场景:
- BigInteger适合保存比较大的整型(整数)
public static void main(String[] args) {
//当我们编程中,需要处理很大的整数,long不够用
//可以使用BigInteger的类来搞定
/*
long l = 14156534156144649999999999L;
System.out.println(l);
//java: 过大的整数: 14156534156144649999999999
*/
BigInteger bigInteger = new BigInteger("14156534156144649999999999");
BigInteger bigInteger2 = new BigInteger("100");
System.out.println(bigInteger);//输出14156534156144649999999999
//我们对 BigInteger 进行加减乘除的时候,需要使用相应的方法,不能直接进行 + - * /
//可以创建一个 要操作的 BigInteger 来进行相应的操作
BigInteger add = bigInteger.add(bigInteger2);//加
System.out.println(add);//输出14156534156144650000000099
BigInteger subtract = bigInteger.subtract(bigInteger2);//减
System.out.println(subtract);//输出14156534156144649999999899
BigInteger multiply = bigInteger.multiply(bigInteger2);//乘
System.out.println(multiply);//输出1415653415614464999999999900
BigInteger divide = bigInteger.divide(bigInteger2);//除
System.out.println(divide);//输出141565341561446499999999
}
- BigDecimal适合保存精度更高的浮点型(小数)
public static void main(String[] args) {
//当我们需要保存一个精度很高的数时,double不够用
//这时候我们可以使用 BigDecimal
/*
double d = 168.99999991111111999222299d;
System.out.println(d);//输出169.0
*/
BigDecimal bigDecimal = new BigDecimal("168.99999991111111999222299");
System.out.println(bigDecimal);//输出168.99999991111111999222299
//我们对 BigDecimal 进行加减乘除的时候,需要使用相应的方法,不能直接进行 + - * /
//可以创建一个 要操作的 BigDecimal 来进行相应的操作
BigDecimal bigDecimal2 = new BigDecimal("1.1");
BigDecimal add = bigDecimal.add(bigDecimal2);//加
System.out.println(add);//输出170.09999991111111999222299
BigDecimal subtract = bigDecimal.subtract(bigDecimal2);//减
System.out.println(subtract);//输出167.89999991111111999222299
BigDecimal multiply = bigDecimal.multiply(bigDecimal2);//乘
System.out.println(multiply);//输出185.899999902222231991445289
//因为除法可能会除不尽,所以可能抛出异常 ArithmeticException
//BigDecimal divide = bigDecimal.divide(bigDecimal2);//除
//处理方法:在调用 divide 方法时,指定精度即可
//bigDecimal2 后面加 BigDecimal.ROUND_CEILING
//如果有无限循环小数,就会保留 分子 的精度
BigDecimal divide = bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING);//除
System.out.println(divide);//输出153.63636355555556362929363
}
11. 日期类(知道怎么查,怎么用即可,不用每个方法都背)
11.1 第一代日期类
-
Date:精确到毫秒,代表特定的瞬间
-
SimpleDateFormat:格式和解析日期的类
-
SimpleDateFormat:格式化和解析日期的具体类。他允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。
- SimpleDateFormat转换日期的格式如下图:
-
应用实例
public static void main(String[] args) throws ParseException {
//第一代日期
//第1种:
// 1.获取当前的时间
// 2.这里的 Date 类是在 java.util 包
// 3.默认输出的日期格式是国外的方式,因此通常需要对格式进行转换
Date d1 = new Date();
System.out.println("当前的时间为 " + d1);
//第2种:
// 通过毫秒数获得一个时间
Date d2 = new Date(999999999);
System.out.println("d2的时间为 " + d2);
//格式转换
// 1.创建 SimpleDateFormat 对象,可以指定相应的格式
// 2.这里的格式使用的字母是规定好的,不能乱写
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
String format = sdf.format(d1);
System.out.println("转换格式后的当前时间为 " + format);
//第3种:
// 1.可以把一个格式化的字符串 转成对应的Date
// 2.得到的 Date 仍然按照国外的格式输出,
// 3.如果希望指定格式输出,需要转换
// 4.在把 String -> Date,使用的 sdf 格式需要和你所写的 Sting 的格式相同
// 否则会抛出转换异常 ParseException
String s = "2012年12月12日 12:12:12 星期三";
Date parse = sdf.parse(s);
System.out.println("parse= " + sdf.format(parse));
}
11.2 第二代日期类
- 第二代日期类,主要就是 Calendar类(日历)
- Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段 (例如获得下星期的日期) 提供了一些方法。
- 应用实例
public static void main(String[] args) {
//第二代日期
//Calendar 解读
//1.Calendar是一个抽象类,并且构造器是protected
//2.可以通过 getInstance() 来获取实例
//3.提供大量的方法和字段提供给程序员
//1.创建日历类对象
//会出现一大堆字段
Calendar calendar = Calendar.getInstance();
System.out.println(calendar);
//2.获取日历对象的某个日历字段
System.out.println("年" + calendar.get(Calendar.YEAR));
//因为 Calendar 返回月的时候,是按照 0 开始编号,所以这里要+1
System.out.println("月" + (calendar.get(Calendar.MONTH) + 1));
System.out.println("日" + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("时" + calendar.get(Calendar.HOUR));
System.out.println("分" + calendar.get(Calendar.MINUTE));
System.out.println("秒" + calendar.get(Calendar.SECOND));
//Calendar 没有专门的格式化方法,所以需要程序员自己来组合显示
System.out.println(calendar.get(Calendar.YEAR) + "年" + (calendar.get(Calendar.MONTH) + 1) + "月" +
calendar.get(Calendar.DAY_OF_MONTH) + "日" + calendar.get(Calendar.HOUR) + "时" +
calendar.get(Calendar.MINUTE) + "分" + calendar.get(Calendar.SECOND) + "秒");
}
11.3 第三代日期类
11.3.1前面两代日期类的不足分析
- JDK 1.0 包含了一个 java.util.Date 类,但是他的大多数方法已经在 JDK 1.1 引入 Calendar 类之后被弃用了。而 Calendar 也存在以下问题:
- 可变性:像日期和时间这样的类应该是不可变的
- 偏移性:Date中的年份是从1900开始的,而月份都是从0开始
- 格式化:格式化只对Date有用,Calendar不可以格式化
- 此外,他们也不是线程安全的;不能处理闰秒等(每隔两天,多出1s)
- 第三类日期常见方法:JDK8时加入
- ① LocalDate(日期):只包含日期,可以获取日期字段
- ② LocalTime(时间):只包含时间,可以获取时间字段
- ③ LocalDateTime(日期时间):包含日期+时间,可以获取日期和时间字段
- 使用 DateTimeFormatter 对象来进行格式化
- 案例演示:
public static void main(String[] args) {
//第三代日期
//1.使用 now 返回当前日期时间的 对象
LocalDateTime ldt = LocalDateTime.now();
//LocalDate.now 只获取日期
//LocalTime.now 只获取时间
System.out.println(ldt);
//2.使用 DateTimeFormatter 对象来进行格式化
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String format = dtf.format(ldt);
System.out.println("格式化的日期= "+format);
/*
//单独获得字段的方法
ldt.getYear();
ldt.getMonthValue();
ldt.getDayOfMonth();
ldt.getHour();
ldt.getMinute();
ldt.getSecond();
*/
System.out.println("年= "+ldt.getYear());//年
System.out.println("月="+ldt.getMonth());//月
System.out.println("月= "+ldt.getMonthValue());//月
System.out.println("日= "+ldt.getDayOfMonth());//日
System.out.println("时= "+ldt.getHour());//时
System.out.println("分= "+ldt.getMinute());//分
System.out.println("秒= "+ldt.getSecond());//秒
}
-
Instant 时间戳:
- 类似于 Date
- 提供了一系列和Date类转换的方式
public static void main(String[] args) { //1.通过静态方法 now() 获取当前时间戳的对象 Instant now = Instant.now(); System.out.println(now); //2.通过 form 可以把 Instant 转成 Date Date date = Date.from(now); //3.通过 date的 toInstant() 可以把 date 转成 Instant 对象 Instant instant = date.toInstant(); }
-
第三代日期类有很多的方法
- LocalDateTime类
- MonthDay类:检查重复时间
- 检查是否是润年
- 增加日期的某个部分
- 使用plus方法测试增加时间的某个部分
- 使用minus方法测试查看一年前和一年后的日期
//提供了 plus 和 minus 方法可以对当前的时间进行 加 或者 减 //看678天后是什么时间 把 年月日-时分秒 输出 LocalDateTime ldt2 = ldt.plusDays(678); System.out.println("678天后的时间= " + dtf.format(ldt2)); //看789分钟前是什么时间 LocalDateTime ldt3 = ldt.minusMinutes(789); System.out.println("789分钟前的时间= " + dtf.format(ldt3));
- 还有很多其他的方法,使用的时候自己查看API使用
12. 本章练习
练习一:
- 将字符串中指定的部分进行反转。比如将"abcdef" 反转为 “aedcbf”*
- 编写方法 public static String reverse(String str,int start,int end) 搞定
- 编码如下:
public class Homework01 {
public static void main(String[] args) {
String str = "abcdef";
System.out.println("最初的str =" + str);//最初的str =abcdef
try {
str = reverse(str, 1, 4);
} catch (Exception e) {
System.out.println(e.getMessage());
return;//如果上面参数不正确,直接不进行下面的步骤
}
System.out.println("反转的str =" + str);//反转的str =aedcbf
}
/**
* 要求
* (1) 将字符串中指定的部分进行反转。比如将"abcdef" 反转为 "aedcbf"
* (2) 编写方法 public static String reverse(String str,int start,int end) 搞定
* 解题思路
* (1) 先确定好方法
* (2) 把 String 转成 char[] ,因为 char[] 的元素是可以交换的
* (3) 防止输出的时候超出实际范围,对输入的参数做一个验证
* (4) 对于参数的验证分享一个重要的编程技巧
* (1) 写出正确的情况
* (2) 然后进行取反就行
*/
public static String reverse(String str, int start, int end) {
//对输入的参数做一个验证
//重要的编程技巧分享
//(1) 写出正确的情况
//(2) 然后进行取反就行
if (!(str != null && start >= 0 && end > start && end < str.length())) {
throw new RuntimeException("参数不正确");
}
char[] chars = str.toCharArray();
char temp = ' ';
for (int i = start, j = end; i < j; i++, j--) {
temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
//使用 chars 重新构建一个 String 即可
return new String(chars);
}
}
练习二:
- 输入用户名、密码、邮箱,如果信息录入正确,则提示注册成功,否则生成异常对象;
- 要求:
- (1) 用户名长度为2、3或4
- (2) 密码长度为6,要求全是数字
- (3) 邮箱中包含 @ 和 . 并且 @ 在 . 的前面 isDigital
- 编码如下:
public class Homework02a {
public static void main(String[] args) {
String name = "sun";
String pwd = "123456";
String email = "1241955497@qq.com";
try {
userRegister(name, pwd, email);
System.out.println("恭喜你,注册成功");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 1. 输入用户名、密码、邮箱,如果信息录入正确,则提示注册成功,否则生成异常对象;
* 2. 要求:
* - (1) 用户名长度为2、3或4
* - (2) 密码长度为6,要求全是数字 isDigital
* - (3) 邮箱中包含 @ 和 . 并且 @ 在 . 的前面
*/
//1.先编写一个方法 userRegister
//2.针对输入的内容进行校验,如果发现问题,就抛出异常,给出提示
//3.单独写一个方法,判断密码是否全部是数字 boolean
public static void userRegister(String name, String pwd, String email) {
//再加入一些校验
if (!(name != null && pwd != null && email != null)) {
throw new RuntimeException("参数不能为空");
}
//1.对用户名进行核验
// 用户名长度为2、3或4
int userLength = name.length();
if (!(userLength >= 2 && userLength <= 4)) {
throw new RuntimeException("用户名长度为2、3或4");
}
//2.对密码进行校验
// 密码长度为6,要求全是数字 isDigital
if (!(pwd.length() == 6 && isDigital(pwd))) {
throw new RuntimeException("密码长度为6,要求全是数字 isDigital");
}
//3.对邮箱进行校验
// 邮箱中包含 @ 和 . 并且 @ 在 . 的前面
int i = email.indexOf("@");
int j = email.indexOf(".");
if (!(i > 0 && i > j)) {
throw new RuntimeException("邮箱中包含 @ 和 . 并且 @ 在 . 的前面");
}
}
//单独写一个方法,判断密码是否全部是数字 boolean
public static boolean isDigital(String str) {
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] < '0' || chars[i] > '9') {
return false;
}
}
return true;
}
}
练习三:
- 编写一个java程序,输入形式为:Sun Yu Song 的人名,以 Song,Sun .Y 的形式打印出来;
- 其中 .Y是中间单词的首字母
- 例如输入 Jack Lucy John,输出形式为 John,Jack.L
- 编码如下:
public class Homework03 {
public static void main(String[] args) {
String name = "Sun Yu Song";
printName(name);//Song,Sun,S
}
/*
编写一个java程序,输入形式为:Sun Yu Song 的人名,以 Song,Sun .Y 的形式打印出来;
- 其中 .Y是中间单词的首字母
- 例如输入 Jack Lucy John,输出形式为 John,Jack.L
*/
//思路分析
//1.对输入的字符串进行分割,split
//2.对得到的String[] 进行格式化String.format
//3.对输入的字符串进行校验即可
public static void printName(String str) {
if (str == null) {
System.out.println("str 不能为空");
return;
}
//把输入的名字进行分割
String[] names = str.split(" ");
if (names.length != 3) {
System.out.println("输入的字符串格式不对");
}
//格式化字符串,%s 字符串, %c 字符, %d 整型, %.2f 浮点型,
String format = String.format("%s,%s,%s", names[2], names[0], names[0].toUpperCase().charAt(0));
System.out.println(format);
}
}
联系四:
- 输入字符串,判断里面有多少个大写字母,有多少个小写字母,多少个数字
- 编码如下:
public class Homework04 {
public static void main(String[] args) {
String str = "shaNJNdasji 1266d";//随便写一串字符
count(str);//调用count方法输出
//数字有4个
//小写字母有9个
//大写字母有3个
//其他字符有1个
}
//输入字符串,判断里面有多少个大写字母,有多少个小写字母,多少个数字
//思路分析
// 1.遍历字符串,如果char在 '0~9' ,就是一个数字
// 2.如果char在 'a~z' ,就是小写字母
// 3.如果char在 'A~Z' ,就是小写字母
// 4.使用三个变量来记录,统计结果
public static void count(String str) {
if (str == null) {
System.out.println("输入不能为空");
}
int strLen = str.length();
int numCount = 0;
int lowerCount = 0;
int upperCount = 0;
int otherCount = 0;
for (int i = 0; i < strLen; i++) {
if (str.charAt(i) >= '0' && str.charAt(i) <= '9') {
numCount++;
} else if (str.charAt(i) >= 'a' && str.charAt(i) <= 'z') {
lowerCount++;
} else if (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') {
upperCount++;
} else {
otherCount++;
}
}
System.out.println("数字有" + numCount + "个");
System.out.println("小写字母有" + lowerCount + "个");
System.out.println("大写字母有" + upperCount + "个");
System.out.println("其他字符有" + otherCount + "个");
}
}