###常用类###
1. Java中的字符串
1) 认识java中的字符串
在程序开发中字符串无处不在,如用户登陆时输入的用户名、密码等使用的就是字符串。
其实,在前面的章节中我们就已经使用了字符串,例如我们在控制台中输出的 "Hello World" 、 "Silvia" 、"Andrew"等。
在 Java 中,字符串被作为 String 类型的对象处理。 String 类位于 java.lang 包中。默认情况下,该包被自动导入所有的程序。
创建 String 对象的方法:
String s1 = "Andrew"; //创建一个字符串对象Andrew,名为s1
String s2 = new String; //chua创建一个空字符串名为s2
String s3 = new String("Andrew") //chu'创建一个字符串对象Andrew,名为s3
例:
package ex.class1;
public class Ex1 {
public static void main(String[] args) {
String s1 = "Andrew";
String s2 = "Silvia";
System.out.println("s1 "+s1+" s2 "+s2);
}
}
2)Java中字符串的不变性
String 对象创建后则不能被修改,是不可变的,所谓的修改其实是创建了新的对象,所指向的内存空间不同。
如:
public class Ex1 {
public static void main(String[] args) {
String s1 = "Andrew";
String s2 = "Andrew";
String s3 = new String("Andrew");
String s4 = new String("Andrew");
System.out.println(s1 == s2);//多次出现的字符常量,Java编译程序只创建一个,所以返回true
System.out.println(s1 == s3);//s1和s3是不同的对象,所以返回值为false
System.out.println(s3 == s4);//s3和s4是不同的对象,所以返回值是false
s1 = "Love "+ s1;//字符串s1被修改,指向新的内存空间
System.out.println(s1);
}
}
结合上述代码,关于字符串我们必须需要了解:
<1> 通过String s1 = "Andrew"; 声明了一个字符串对象,s1存放了到字符串对象的引用,在内存中的存放引用关系如图
然后通过 s1="欢迎来到:"+s1; 改变了字符串 s1 ,其实质是创建了新的字符串对象,变量 s1 指向了新创建的字符串对象,如图
<2> 一旦一个字符串在内存中创建,则这个字符串将不可改变。如果需要一个可以改变的字符串,我们可以使用StringBuffer或者StringBuilder。
<3> 每次 new 一个字符串就是产生一个新的对象,即便两个字符串的内容相同,使用 ”==” 比较时也为 ”false” ,如果只需比较内容是否相同,应使用 ”equals()” 方法
例:
public class Ex1 {
public static void main(String[] args) {
String s1 = "Andrew";
String s2 = "Andrew";
String s3 = "Love "+ s1;
//定义字符串s3,保存“love”和s1拼接后的内容
// 比较字符串s1和s2
// Andrew为常量字符串,多次出现时会被编译器优化,只创建一个对象
System.out.println("s1和s2内存地址相同吗?" + (s1 == s2));
//比较字符串s1和s3
System.out.println("s1和s3内存地址相同吗?" + (s1 == s3));
String s4 = "love " + s1;
//比较字符串s4和s3
// s1是变量,s4在运行时才知道具体值,所以s3和s4是不同的对象
System.out.println("s3和s4内存地址相同吗?" + (s4 == s3));
}
}
3)String类的常用方法
<1> String 类提供了许多用来处理字符串的方法,例如,获取字符串长度、对字符串进行截取、将字符串转换为大写或小写、字符串 分割等。
String 类的常用方法:
结合代码来熟悉一下方法的使用:
package ex.class1;
import java.util.Arrays;
public class Ex2 {
public static void main(String[] args) {
String s1 = "And rew";
//定义一个字符串"And rew"
System.out.println("字符串长度:"+s1.length());
//打印出字符串长度
char c = 'd';
System.out.println("字符‘d’的位置:"+s1.indexOf(c));
System.out.println("字符‘And’的位置:"+s1.indexOf("And"));
//查找字符串'And'的位置
System.out.println("字符‘Sil’的位置"+s1.indexOf("Sil"));
//查找字符串'Sil'的位置,如果找不到返回-1
String[] arr = s1.split(" ");
//按空格把字符串拆分成一个数组,并输出数组元素
System.out.println("按空格拆分成数组:"+Arrays.toString(arr));
System.out.println("获取位置[2,5)之间的字串:"+s1.substring(2,5));
//获取索引[2,5)之间的字串
}
}
ps:
1. 字符串 s1 中字符的索引从0开始,范围为 0 到 str.length()-1
2. 使用 indexOf 进行字符或字符串查找时,如果匹配返回位置索引;如果没有匹配结果,返回 -1
3. 使用 substring(beginIndex , endIndex) 进行字符串截取时,包括 beginIndex 位置的字符,不包括 endIndex 位置的字符
例题:判断 Java 文件名是否正确,判断邮箱格式是否正确。其中:合法的文件名应该以 .java 结尾;合法的邮箱名中至少要包含 “@” , 并要求 “@” 在 “.” 之前
package ex.class1;
public class Ex3 {
public static void main(String[] args) {
// Java文件名
String fileName = "HelloWorld.java";
// 邮箱
String email = "[email protected]";
// 判断.java文件名是否正确:合法的文件名应该以.java结尾
/*
参考步骤:
1、获取文件名中最后一次出现"."号的位置
2、根据"."号的位置,获取文件的后缀
3、判断"."号位置及文件后缀名
*/
//获取文件名中最后一次出现"."号的位置
int index = fileName.lastIndexOf(".");
// 获取文件的后缀
String prefix = fileName.substring(index + 1, fileName.length());
// 判断必须包含"."号,且不能出现在首位,同时后缀名为"java"
if (index != -1 && index !=0 && prefix.equals("java")) {
System.out.println("Java文件名正确");
} else {
System.out.println("Java文件名无效");
}
// 判断邮箱格式是否正确:合法的邮箱名中至少要包含"@", 并且"@"是在"."之前
/*
参考步骤:
1、获取文件名中"@"符号的位置
2、获取邮箱中"."号的位置
3、判断必须包含"@"符号,且"@"必须在"."之前
*/
// 获取邮箱中"@"符号的位置
int index2 = email.indexOf('@');
// 获取邮箱中"."号的位置
int index3 = email.indexOf('.');
// 判断必须包含"@"符号,且"@"必须在"."之前
if (index2 != -1 && index3 > index2) {
System.out.println("邮箱格式正确");
} else {
System.out.println("邮箱格式无效");
}
}
}
<2> “==” 和 equals() 的区别
==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象
equals(): 比较存储在两个字符串对象中的内容是否一致
PS:字节是计算机存储信息的基本单位,1 个字节等于 8 位, gbk 编码中 1 个汉字字符存储需要 2 个字节,1 个英文字符存储需要 1 个字节。所以每个汉字对应两个字节值。同时,我们还发现汉字对应的字节值为负数,原因在于每个字节是 8 位,最大值不能超过 127,而汉字转换为字节后超过 127,如果超过就会溢出,以负数的形式显示。
例题:统计指定字符串中字符 ‘a’ 出现的次数
public class Ex4 {
public static void main(String[] args) {
// 定义一个字符串
String s = "silvia love andrew and andrew love silvia too";
// 出现次数
int num = 0;
// 循环遍历每个字符,判断是否是字符 a ,如果是,累加次数
for (int i = 0 ; i< s.length(); i++)
{
// 获取每个字符,判断是否是字符a
if (s.charAt(i) == 'a') {
// 累加统计次数
num++;
}
}
System.out.println("字符a出现的次数:" + num);
}
}
4)Java中的StringBuffer:线程安全的可变字符序列(线程安全--->同步---->执行效率低)
StringBuffer(容器)和String的区别?
前者是线程安全的类,可变的字符序列,内存中提供字符串缓冲区;后者是不可变的字符序列
从内存角度考虑:前者优于后者: String类型:在方法区中开辟空间--->占内存
StringBuffer :里面存在初始容量,里面不断的追击字符串(append)
StringBuffer的构造方法:
public StringBuffer()构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。
public StringBuffer(int capacity):指定容量大小
public StringBuffer(String str):构造一个字符串缓冲区:里面的容量(字符串内容英文)大小:字符串长度+16初始容量
获取功能:
public int capacity():初始容量
int length():返回字符串长度
例:
public class Ex5 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
System.out.println(sb);
System.out.println("length():"+sb.length());
System.out.println("capacity():"+sb.capacity());
System.out.println("--------------------------------");
//public StringBuffer(int capacity):指定容量大小
StringBuffer sb2 = new StringBuffer(50);
System.out.println("length():"+sb2.length());
System.out.println("capacity():"+sb2.capacity());
System.out.println("--------------------------------");
//StringBuffer类似于String类型的缓冲区
StringBuffer sb3 = new StringBuffer("hello") ;
System.out.println(sb3);
System.out.println("length():"+sb3.length());
System.out.println("capacity():"+sb3.capacity());
}
}
StringBuffer的添加功能:StringBuffer append(xxx x):将指定的内容追加(末尾追加)到字符串缓冲区中,返回StringBuffer本身
public StringBuffer insert(int index,xxx x):在指定位置处,插入一个新的内容,返回StringBuffer本身
public static void main(String[] args) {
//创建一个字符串缓冲区
StringBuffer sb = new StringBuffer() ;
System.out.println(sb);
// 链式编程
sb.append("Silvia").append(true).append('a').append(100).append(12.34) ;
System.out.println("sb:"+sb);
//public StringBuffer insert(int index,xxx x)
sb.insert(5, "via") ;
System.out.println("sb:"+sb);
}
StringBuffer的删除功能:
StringBuffer deleteCharAt(int index) :删除指定位置出的字符,返回字符串缓冲区本身
StringBuffer delete(int start, int end) :删除从指定位置开始到指定位置结束,返回值字符串缓冲区本身
public static void main(String[] args) {
//创建字符串缓冲区
StringBuffer sb = new StringBuffer() ;
//添加内容
sb.append("Silvia").append("Andrew") ;
System.out.println(sb);
//需求:要删除:e这个字符
sb.deleteCharAt(1) ;
System.out.println(sb);
//需求:删除第一个l这个字符
System.out.println(sb.deleteCharAt(1));
//StringBuffer delete(int start, int end)
System.out.println(sb.delete(3, 5)); //包前不包后
}
StringBuffer的替换功能:
public StringBuffer replace(int start,int end,String str)
从指定位置开始到指定位置结束,用给定的str字符串替换指定的字符内容
public static void main(String[] args) {
//构造一个字符串缓冲区
StringBuffer sb = new StringBuffer() ;
//追加
sb.append("Silvia") ;
sb.append(" Love ") ;
sb.append("Andrew") ;
System.out.println(sb);
System.out.println(sb.replace(6, 11, " ☆ "));
}
StringBuffer的反转功能:
public static void main(String[] args) {
StringBuffer s = new StringBuffer() ;
s.append("我爱竹竹") ;
System.out.println("s:"+s);
s.reverse() ;
System.out.println("s:"+s);
}
StringBuffer的截取功能:
String substring(int start) :从指定位置默认截取到末尾,返回一个新的字符串
String substring(int start,int end):从指定位置开始截取到指定位置结束
public static void main(String[] args) {
//创建缓冲区对象
StringBuffer sb = new StringBuffer() ;
sb.append("Silvia") ;
sb.append("Love") ;
sb.append("Andrew") ;
System.out.println(sb.substring(3, 8));
System.out.println(sb);
}
String与StringBuffer间的相互转换
public static void main(String[] args) {
//String--->StringBuffer
String s ="Silvia" ;
StringBuffer sb = new StringBuffer() ;
sb.append(s) ;
System.out.println(sb);
System.out.println("-----------------------------");
//StringBuffer--->String
StringBuffer buffer = new StringBuffer("Andrew") ;
// 方式1:String类型的构造方法 String(StringBuffer buffer)
//创建一个String
String str = new String(buffer) ;
System.out.println("str:"+str);
//方式2:StringBuffer()里面toString():将StringBuffer--->String
String str2 = buffer.toString() ;
System.out.println("str2:"+str2);
}
例1:把数组拼接成一个字符串 int[] arr [11,22,33,44,55]
方法改进分别使用:String 和StringBuffer
public class Ex7 {
public static void main(String[] args) {
int[] arr = {11,22,33,44,55} ;
//使用StringBuffer
String result = arrayToString(arr) ;
System.out.println("result:"+result);
}
public static String arrayToString(int[] arr) {
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
//追加左中括号
sb.append("[") ;
//遍历数组
for(int x = 0 ; x < arr.length ; x ++) {
//判断是否最大值索引
if(x==arr.length-1) {
sb.append(arr[x]).append("]") ;
}else {
sb.append(arr[x]).append(", ") ;
}
}
return sb.toString();
}
}
例2:键盘录入字符串判断是否是对称字符串, 例如"abc"不是对称字符串,"aba"、"abba"、"aaa"、"mnanm"是对称字符串
分析:
1)键盘录入字符串
2)字符数组
3)拿0索引--->数组长度-1 ... ... ... 保证数组长度/2
public class Ex8 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//接收数据
System.out.println("请输入一个字符串:");
String line = sc.nextLine() ;
boolean flag = isSame(line) ;
System.out.println("flag:"+flag);
}
StringBuffer的方法:
public static boolean isSame2(String s) {
//链式编程:
//返回本身StringBuffer
return new StringBuffer(s).reverse().toString().equals(s) ;
}
传统方法:
public static boolean isSame(String s) {
//假设为true
boolean flag = true ;
//可以将字符串转换成字符数组
char[] chs = s.toCharArray() ;
//遍历数组
for(int start = 0 , end = chs.length-1 ; start<=end ; start++,end--) {
//判断
if(chs[start]!=chs[end]) {
//修改标记
flag = false ;
break ;
}
}
return flag ;
}
2. Java中的包装类:基本数据类型是不具备对象的特性的,比如基本类型不能调用方法、功能简单。为了让基本数据类型也具备对象的特性, Java 为每个基本数据类型都提供了一个包装类,这样我们就可以像操作对象那样来操作基本数据类型。
1)基本类型和包装类之间的对应关系:
包装类主要提供了两大类方法:
1. 将本类型和其他基本类型进行转换的方法
2. 将字符串和本类型及包装类互相转换的方法
我们以 Integer 包装类为例,来看下包装类的特性。
Integer 包装类的构造方法:
Integer包装类的常用方法:
例:
public static void main(String[] args) {
// 定义int类型变量,值为86
int score1 = 86;
// 创建Integer包装类对象,表示变量score1的值
Integer score2=new Integer(score1);
// 将Integer包装类转换为double类型
double score3=score2.doubleValue();
// 将Integer包装类转换为float类型
float score4=score2.floatValue();
// 将Integer包装类转换为int类型
int score5 =score2.intValue();
System.out.println("Integer包装类:" + score2);
System.out.println("double类型:" + score3);
System.out.println("float类型:" + score4);
System.out.println("int类型:" + score5);
}
2)Java 中基本类型和包装类之间的转换
基本类型和包装类之间经常需要互相转换,以 Integer 为例:
Integer a = new Integer(3);//定义Integer包装类对象,值为3
int b = a + 5; //将对象和基本类恶性进行运算
在 JDK1.5 引入自动装箱和拆箱的机制后,包装类和基本类型之间的转换就更加轻松便利了。
装箱:把基本类型转换成包装类,使其具有对象的性质,又可分为手动装箱和自动装箱
int i = 10; //定义一个int基本类型值
Integer x = new Integer(i); //手动装箱
Integer y = i; //自动装箱
拆箱:和装箱相反,把包装类对象转换成基本类型的值,又可分为手动拆箱和自动拆箱
Integer i = new Integer(8); //定义一个Integer包装类对象,值为8
Int m = i.intValue(); //手动拆箱为int类型
int n = i; //自动拆箱为int类型
例:
public static void main(String[] args) {
// 定义double类型变量
double a = 91.5;
// 手动装箱
Double b = new Double(a);
// 自动装箱
Double c = a;
System.out.println("装箱后的结果为:" + b + "和" + c);
// 定义一个Double包装类对象,值为8
Double d = new Double(87.0);
// 手动拆箱
double e = d.doubleValue();
// 自动拆箱
double f = d;
System.out.println("拆箱后的结果为:" + e + "和" + f);
}
3)Java 中基本类型和字符串之间的转换
在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换。
其中,基本类型转换为字符串有三种方法:
1. 使用包装类的 toString() 方法
2. 使用String类的 valueOf() 方法
3. 用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串
//将基本类型转化为字符串
int a = 521;
String str1 = Integer.toString(a); //方法1
String str2 = String.valueOf(a); //方法2
String str3 = a + ""; //方法3
将字符串转换成基本类型有两种方法:
1. 调用包装类的 parseXxx 静态方法
2. 调用包装类的 valueOf() 方法转换为基本类型的包装类,会自动拆箱
//将字符串类型转换为基本类型
String str = "521";
int a = Integer.parseInt(str); //方法1
int b = Integer.valueOf(str); //方法2
4)使用Date和SimpleDateFormat类表示时间
在程序开发中,经常需要处理日期和时间的相关数据,此时我们可以使用 java.util 包中的 Date 类。这个类最主要的作用就是获取当前时间,我们来看下 Date 类的使用:
Date d = new Date(); //使用默认的构造方法创建Date对象
System.out.println(d); //输出Date对象
使用 Date 类的默认的午餐构造方法创建出的对象就代表当前时间,我们可以直接输出 Date 对象显示当前的时间,显示的结果如下:
其中,Thu 代表Thursday(星期四), Jun 代表August(八月), 02 代表 2 号, CST 代表 China Standard Time (中国标准时间,也就是北京时间,东八区)。
从上面的输出结果中,我们发现,默认的时间格式不是很友好,与我们日常看到的日期格式不太一样,如果想要按指定的格式进行显示,如 2018-02-14 14:36:48 ,那该怎么做呢?
此时就到了 java.text 包中的 SimpleDateFormat 类大显身手的时候了!!可以使用 SimpleDateFormat 来对日期时间进行格式化,如可以将日期转换为指定格式的文本,也可将文本转换为日期。
1. 使用 format() 方法将日期转换为指定格式的文本
//创建Date,表示当前时间
Date d = new Date();
//创建SimpleDateFormat对象,指定目标格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//调用format()方法,格式化时间,转换为制定格式字符串
String today = sdf.format(d);
//输出转换后字符串
System.out.printlin(today);
代码中的 “yyyy-MM-dd HH:mm:ss” 为预定义字符串, yyyy 表示四位年, MM 表示两位月份, dd 表示两位日期, HH 表示小时(使用24小时制), mm 表示分钟, ss 表示秒,这样就指定了转换的目标格式,最后调用 format() 方法将时间转换为指定的格式的字符串。
运行结果: 2018-02-14 14:36:48
2. 使用 parse() 方法将文本转换为日期
//创建日期格式的字符串
String day = "2018年08月02日 14:36:48"
//创建SimpleDateFormat对象,指定字符串格式
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//调用format()方法,格式化时间,转换为制定格式字符串
Date date = df.parse(day);
//输出转换后时间
System.out.printlin("当前时间:"+day);
代码中的 “yyyy年MM月dd日 HH:mm:ss” 指定了字符串的日期格式,调用 parse() 方法将文本转换为日期。
运行结果: Thu Aug 02 14:36:48 CST
PS:
1、 调用 SimpleDateFormat 对象的 parse() 方法时可能会出现转换异常,即 ParseException ,因此需要进行异常处理
2、 使用 Date 类时需要导入 java.util 包,使用 SimpleDateFormat 时需要导入 java.text 包
4)Calendar类的应用
Date 类最主要的作用就是获得当前时间,同时这个类里面也具有设置时间以及一些其他的功能,但是由于本身设计的问题,这些方法却遭到众多批评,不建议使用,更推荐使用 Calendar 类进行时间和日期的处理。
java.util.Calendar 类是一个抽象类,可以通过调用 getInstance() 静态方法获取一个 Calendar 对象,此对象已由当前日期时间初始化,即默认代表当前时间,如 Calendar c = Calendar.getInstance();
那么如何使用 Calendar 获取年、月、日、时间等信息呢?我们来看下面的代码:
import java.util.Calendar;
public class Ex11 {
public static void main(String[] args) {
Calendar c = Calendar.getInstance(); //创建Calendar对象
int year = c.get(Calendar.YEAR); //获取年
int month = c.get(Calendar.MONTH)+1; //获取月份,0表示1月
int day = c.get(Calendar.DAY_OF_MONTH); //获取日期
int hour = c.get(Calendar.HOUR_OF_DAY); //获取小时
int minute = c.get(Calendar.MINUTE); //获取分钟
int second = c.get(Calendar.SECOND); //获取秒
System.out.println("当前时间: "+year+"-"+month+"-"+day+" "+hour+":"+minute+":"+second);
}
}
其中,调用 Calendar 类的 getInstance() 方法获取一个实例,然后通过调用 get() 方法获取日期时间信息,参数为需要获得的字段的值, Calendar.Year 等为 Calendar 类中定义的静态常量。
运行结果: 当前时间: 2018-8-2 15:0:5
Calendar 类提供了 getTime() 方法,用来获取 Date 对象,完成 Calendar 和 Date 的转换,还可通过 getTimeInMillis() 方法,获取此 Calendar 的时间值,以毫秒为单位。如下所示:
import java.util.Calendar;
public class Ex11 {
public static void main(String[] args) {
Date d = c.getTime(); //将Calendar对象转换为Date对象
Long time = c.getTimeInMillis(); //获取当前毫秒
System.out.println("当前时间: "+ d);
System.out.println("当前毫秒数: "+ time);
}
}
运行结果: 当前时间: Thu Aug 02 15:03:06 CST 2018
当前毫秒数: 1533193386182
5)使用Math类操作数据
Math 类位于 java.lang 包中,包含用于执行基本数学运算的方法, Math 类的所有方法都是静态方法,所以使用该类中的方法时,可以直接使用类名.方法名,如: Math.round();
常用的方法:
例:
package ex.class2;
public class Ex12 {
public static void main(String[] args) {
double a = 15.38;
int b = (int) a;
System.out.println("强制类型转换:"+b);
long c = Math.round(a);
System.out.println("四舍五入:"+c);
double d = Math.floor(a);
System.out.println("floor:"+d); //调用floor方法,返回小于参数的最大整数
double e = Math.ceil(a);
System.out.println("ceil:"+e); //调用ceil方法,返回大于参数的最小整数
double x = Math.random();
System.out.println("随机数:"+x); //调用random方法,产生[0,1)之间的随机数浮点数
int y = (int) (Math.random()*99); //产生[0,99)之间的随机数
System.out.println("产生[0,99)之间的随机整数:"+ y);
}
}
####END####