提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- String字符串类
- String
- 可变字符串
- StringBuilder
- 可变字符串与String之间的转换
- RunTime类
- 概述
- 特点
- 使用
- Data类
- 方法
- SimpleDateFormat类
- 方法
- 包装类
- 特点
- 字符串与原始类型之间的转换
- 异常
- 异常的产生
- 异常的类型
- 处理异常
- try-catch-finally语句
- throws关键字
- throw和throws
- 自定义异常
- 使用
- 集合
- 特点
- 集合的框架
- Collection接口
- List接口(有序可重复)
- ArrayList实现类
- 常用方法
- 例子
- LinkedList实现类
- 特点
- 常用方法
- 例子
- ArrayList和LinkedList的区别
- Set接口(无序不重复)
- TreeSet实现类
- 常用方法
- 例子
- Map接口
- 常用方法
- HashMap实现类
- 遍历集合中元素的方式
前言
本周学习了Java高级阶段,主要是学习java自带的各种类的用法,内容稍多,重点在于集合的使用方面。
String字符串类
String
String的创建赋值例如:String str = “希希”; 字符串用"内容"定义之后,值不可改变;而str = “西西” ;是重新创建一个String并把地址保存在str中
String str = "希希"; //创建String
str = "西西" ; //一个String将地址保存给str
再例如:
String s7 = new String("春娇"); //常量池:"春娇",堆:new String()
String s8 = s7 + "志明"; //常量池:"志明" 堆:new StringBuilder()
//4个对象:常量池:”春娇"和"志明",堆:new String()和new StringBuilde
注意
使用字符串进行比较是否相同时,因为是比较内存地址,所以不要用==比较,要使用重写后的.equals进行比较。
可变字符串
StringBuilder
因为String创建之后,值不会改变,如果要频繁的改变字符串的值,就要用到StringBuilder
StringBuilder = strb = new StringBuilder();
strb.append("千玺"); //这样就可以直接修改字符串的值
StringBuilder更新赋值操作全程只会有一个StringBuilder,赋值只操作对象,不会创建新对象,效率很高。
注意
StringBuilder属于非线程安全,建议单线程使用
多线程建议使用StringBuffer
可变字符串与String之间的转换
String转换为可变字符串
String str="hello";
StringBuilder sb = new StringBuilder(str)
可变字符串转换为String
StringBuilder sb = new StringBuilder("你好");
String str = String.valueOf(sb)
RunTime类
概述
Runtime类的对象,表示程序运行时对象(程序运行环境对象)。
包含了程序运行环境相关的信息。常用于获取运行环境信息(如虚拟机内存)或执行某个命令。
特点
这个类不是一个抽象类,但不能创建对象,因为它的构造方法是私有的。
这个类提供了一个静态方法getRuntime(),通过这个方法,可以获取一个Runtime类的对象。
这是Java中的一种设计模式–单例模式(一个类只能有一个创建对象)。
使用
runtime.freeMemory() //得到当前虚拟机的空闲内存
runtime.totalMemory() //得到当前虚拟机最大内存
runtime.maxMemory() //得到当前虚拟机所支持最大内存
注意
public static void fun(char[] list,Person p){
list[0]='m';//这里在直接操作实际参数,会影响实参
p = new Person();//这里创建了一个新的对象,操作的是方法中的对象,不会影响实参
p.setName("刘鑫");
}
public static void main(String[] args){
char[] list={'a','b','c'};
Person p = new Person();
fun(list,p);
System.out.println(list[0]);//方法内部直接操作数组,会影响实际参数,输出m
System.out.println(p.getName());//方法内部创建了新对象,不会影响实际参数,输出null
}
Data类
用于表示日期时间的类,位于java.util包下
方法
Date date = new Date();
System.out.println(date);
会打印这种格式的当前时间
常用方法
getTime() //得到对应Date对象表示的毫秒数
setTime(long l) //设置Date对象的毫秒数
after(Date when) //判断调用日期对象是否在when之后
before(Date when) //判断调用日期对象是否在when之前
SimpleDateFormat类
方法
SimpleDateFormat(String pattern); //创建一个指定日期模板的格式化日期对象
日期模板
yyyy 年份
MM 月份
dd 日期
HH 小时
mm 分钟
ss 秒
E 星期
以上两个字母都可以写成一个,如月份5 M:5,MM:05
yyyy/MM/dd HH:mm:ss E 2022/11/24 16:24:09 星期四
例如:
String patten = "yyyy/MM/dd HH:mm:ss E";//年/月/日 时:分:秒 星期
//创建格式化日期类对象,参数为日期模板
SimpleDateFormat sdf = new SimpleDateFormat(patten);
Date now = new Date();
//调用格式化日期对象的format(Date date),将Date对象转换为指定日期格式的字符串
String format = sdf.format(now);
//输出
System.out.println(format);
//parse(String str)将指定日期模板的字符串转换为Date对象
Date date = sdf.parse("2000/5/3 2:1:3 星期一");
System.out.println(date);
包装类
包装类就是原始类型对应的类类型。包装类通常用于字符串与原始类型之间的转换。
在web应用中,从浏览器页面中获取到后台的数据,全部都是String类型,所以一定要使用转换为原始
类型的方法。
包装类 | 原始类型 |
Byte | byte |
Short | short |
Integer | int |
Long | long |
Float | float |
Double | double |
Character | char |
Boolean | boolean |
特点
- 八个原始类型中,除了int和char,其余类型的包装类,都是将首字母改为大写。int对应Integer,char对应Character
- 包装类都是被final修饰的,不能被继承
- 除了Character类,其余包装类都有两个构造方法:参数为原始类型或String的构造方法。
- Character的构造方法只有一个,参数为char类型。这些构造方法用于将原始类型或字符串转换为包装类对象
- 除了Character类,其余类都有静态方法parse原始类型(String str),用于将字符串转换为相应的原始类型
- 数值型的包装类的parseXXX()方法,如果参数不是对应的数字,转换时就会抛出
- NumberFormat异常。如"123abc",或"123.4",在使用Integer.parseInt()时都会抛出异常
- Boolean类型中的parseBoolean()方法,参数如果是"true"这四个字母,不区分大小写,都能转换为真正boolean类型的true,只要不是"true"这个单词,转换结果都为false
- 除了Boolean类,其余包装类都有MAX_VALUE和MIN_VALUE这两个静态属性,用于获取对应类型支持的最大最小值
- 所有包装类都重写了toString()方法,用于将包装类对象转换为String对象
字符串与原始类型之间的转换
使用原始类型对应的包装类,调用parse原始类型(字符串)方法
String num="123";
byte b = Byte.parseByte(num);//123
short s = Short.parseShort(num);//123
int i = Integer.parseInt(num);//123
long l = Long.parseLong(num);//123
float f = Float.parseFloat(num);//123.0
double d = Double.parseDouble(num);//123.0
boolean flag = Boolean.parseBoolean(num);//false
异常
当程序没有按开发人员的意愿正常执行,中途出现错误导致程序中断,出现这种情况,就称为异常。
异常的产生
异常在程序中以对象的形式存在。当代码执行过程中出现异常,虚拟机会自动创建一个异常对象,如果
没有对象该异常对象进行处理,就会导致程序中断,不再执行后续代码。
异常的类型
运行时异常
常见运行时异常 | 出现的情景 |
NullPointerException | 用空对象null调用属性或方法 |
ArrayIndexOutOfBoundsException | 使用数组时,下标超出范围 |
NumberFormatException | 使用包装类调用parse方法做转换时,无法 |
InputMismatchException | 使用Scanner接收控制台输入时,如果不满足接收的类型。如int i = sc.nextInt(),实际输入a |
ClassCastException | Person p = (Person)Object obj; |
ArithmeticException | 0当分母 |
编译时异常
如果一个异常类属于Exception异常类的子类,称为编译时异常,无法通过编译,必须处理异常后
才能编译运行。
常见编译时异常 | 出现的情景 |
SQLException | 操作数据库时 |
IOException | 使用流对象时 |
FileNotFoundException | 方法的参数为文件时 |
处理异常
try-catch-finally语句
try{
//可能出现异常的代码
}catch(异常类 异常对象){
//如果出现异常对象,且与catch小括号中的异常类型匹配,就会执行这里的代码
}catch(异常类 异常对象){
//如果出现异常对象,且与catch小括号中的异常类型匹配,就会执行这里的代码
}finally{
//无论程序是否会抛出异常,都要执行的代码
}
注意
try、catch、finally都不能单独使用,try需要配合catch或finally或catch和finally一起使用
执行try中的内容时,当某行代码抛出异常,不再执行try中该行代码后续的内容
无论try中的代码是否会抛出异常,finally中的代码一定会执行
在try中定义的内容,无法在try之外的地方使用
try中如果有return,不影响finally的执行,finally优先于return执行
throws关键字
使用throws关键字直接将异常抛出,让程序通过编译
public void fun() throws InterruptException{//这时该方法就会有一个声明:该方法可能会抛出异常
//这句话直接写完后,会报错,因为sleep()方法可能会抛出InterruptException异常,属于编译时异常,必须要处理
Thread.sleep(500);
}
throw和throws
throws表示用于声明方法有可能出现的异常。使用时写在方法的小括号之后
public void fun() throws InterruptException{
Thread.sleep(500);
}
throw用于手动抛出异常对象。使用时,写在方法体中,常用于满足某种情况时,强制中断程序
用法:throw 异常对象;
public void fun2(){
for(int i=0;i<10;i++){
if(i==5){
//手动抛出异常
throw new NullPointerException();
}
}
}
自定义异常
如果需要在某种情况下中断程序, 可以自定义一个异常类,再通过throw关键字手动抛出。
使用
先创建一个异常类
public class MyException extends RuntimeException{
public MyException(String message) {
super(message); //message代表异常触发时,输出什么样的提示
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int connt=0;
while (true)
{
System.out.print("请输入密码:");
String pwd = scanner.nextLine();
int yue = 0;
if (connt==3)
{
throw new moneyEx("密码错误三次,程序终止"); //在这里用throw关键字抛出异常
} //这里输入要提示的内容
//验证密码
if (!pwd.equals("123")) {
System.out.println("请重新输入密码");
connt++;
}
if (pwd.equals("123"))
{
//菜单内容
}
再写好触发条件与触发后提示内容
集合
特点
- 能保存一组数据,可以有序可以无序
- 集合的容量可变
- 集合中可以保存不同类型的数据
- 可以获取集合中保存的元素实际数量
集合的框架
集合的根接口为Collection接口和Map接口
Collection接口
该接口有两个核心子接口:List和Set。
这两个接口都可以保存一组元素,List接口保存元素时,是有序可重复的;Set接口保存元素时,是无序
不重复的。
List接口(有序可重复)
ArrayList实现类
常用方法
例子
public static void main(String[] args) {
//创建一个空集合,实际会创建一个Object类型的空数组
ArrayList arrayList = new ArrayList();
//添加元素到末尾
arrayList.add(3);//这里的3不是int类型,而是Integer类型
arrayList.add("hello");
arrayList.add("hello");
arrayList.add(null);
arrayList.add(false);
//添加元素到指定索引,效率低,因为会影响指定索引之后的元素
arrayList.add(0, "first");
//根据元素删除第一次出现的元素,效率低,因为会影响被删除元素之后的元素
boolean flag = arrayList.remove("hello");
//根据指定索引删除,返回被删除的元素
Object remove = arrayList.remove(3);
//得到指定索引的元素
Object o = arrayList.get(0);
System.out.println(o);
//集合可以获取实际的元素数量
int size = arrayList.size();
System.out.println(size);
//判断集合中是否存在某个元素
System.out.println(arrayList.contains("first"));
//替换集合中指定索引对应的元素,返回被替换的元素
Object set = arrayList.set(0, "set");
System.out.println(set);
//清空集合
// arrayList.clear();
//判断集合是否为空
System.out.println(arrayList.isEmpty());
//得到某个元素第一次出现的索引
System.out.println(arrayList.indexOf(false));
//截取索引为[from,to)区间内的元素
List list = arrayList.subList(1, 3);
System.out.println(list);
//将集合转换为数组
System.out.println(arrayList.toArray()[2]);
//如果直接输出集合对象,会调用重写后的toString()方法,输出集合中的所有元素
System.out.println(arrayList);
}
LinkedList实现类
特点
- 采用双向链表实现的集合
- 集合中保存的每个元素也称为节点,除首尾节点外,其余节点都保存了自己的信息外,还保存了其前一个和后一个节点的地址
- 如果在双向链表的数据结构中插入和删除操作节点时,不会影响其他节点的位置。如添加时新节点时,只需要重写定义新节点的前后节点位置即可
- 如果要查询某个节点时,需要从头结点或尾结点开始一步步得到目标节点的位置
- 双向链表在中间插入和删除的效率高,随机读取的效率低
常用方法
例子
public static void main(String[] args) {
LinkedList<String> namelist = new LinkedList();
namelist.add("梅西");
namelist.add("c罗");
namelist.add("凯恩");
namelist.add("德布劳内");
namelist.add("内马尔");
int i = namelist.indexOf("c罗");
namelist.add(i,"莱万");
namelist.add(namelist.indexOf("莱恩")+1,"莫德里奇");
namelist.addLast("姆巴佩");
namelist.set(namelist.indexOf("凯恩"),"格列");
namelist.remove("德布劳内");
System.out.println(namelist);
}
ArrayList和LinkedList的区别
- 这两个类都是List接口的实现类,保存的元素有序可重复,允许保存null
- ArrayList采用数组实现,随机读取效率高,插入删除效率低,适合用于查询
- LinkedList采用双向链表实现,插入删除时不影响其他元素,效率高,随机读取效率低,适合用于 频繁更新集合
Set接口(无序不重复)
无序集合,元素不可以重复,允许保存null,没有索引。
Set接口中没有自己定义的方法,都是继承于Collection接口中的方法
TreeSet实现类
特殊的Set实现类,数据可以有序保存,可以重复,不能添加null
采用红黑树实现的集合
常用方法
例子
public int compareTo(Object o) {
//此时this是当前添加的对象
//o是已存在的集合中的对象
Employee emp = (Employee) o;
//这里用当前员工号-已有员工号,根据员工号升序
return this.getNo()-emp.getNo();
//根据姓名字符串的排序方式排序
// return emp.getName().compareTo(this.getName());
}
public static void main(String[] args) {
TreeSet<Employee> emps = new TreeSet<>();
Employee e1 = new Employee(10023,"aaa","市场部");
Employee e2 = new Employee(10025,"ccc","市场部");
Employee e3 = new Employee(10028,"bbb","市场部");
Employee e4 = new Employee(10028,"xxx","市场部");
//第一个元素直接添加
emps.add(e1);
//第二个元素添加时,调用compareTo()方法 e2.compareTo(e1) e2.10025 -
e1.10023 结果为正,添加在现有元素之后
emps.add(e2);
emps.add(e3);
//添加该元素时,调用compareTo()方法 e4.10028 - e3.10028 结果为0,不添加
emps.add(e4);
for (Employee emp : emps) {
System.out.println(emp);
}
}
使用重写后的方法 可以控制集合的降序与升序
Map接口
Map称为映射,数据以键值对的形式保存。保存的是键与值的对应关系。
键称为Key,值称为Value,键不能重复,键允许出现一个null作为键,值无限制。
键和值都是引用类型。
如,yyds就是一个键key,代表了一个含义:“永远单身”即为值value。
常用方法
HashMap实现类
例子
public static void main(String[] args) throws ParseException {
HashMap hp = new HashMap();
hp.put("lol","英雄联盟");
//向集合中添加一组键值对
hp.put("pubg","绝地求生");
hp.put("cs","反恐精英");
System.out.println(hp);
System.out.println("get"+hp.get("lol"));
//在集合中根据键得到对应的值
System.out.println("size"+hp.size());
//得到键值对的数量
System.out.println("keySet"+hp.keySet());
//获取键的集合
System.out.println("values"+hp.values());
//获取值的集合
System.out.println("containsKey"+hp.containsKey("cs"));
//判断是否存在某个键
System.out.println("containsValue"+hp.containsValue("英雄联盟"));
//判断是否存在某个值
System.out.println("entrySet"+hp.entrySet());
//得到键值对的集合
}
注意
HashMap中,用put方法存放两个键相同值不同的键值对时,编译不会报错,后添加的会自动替换添加好的键值对
添加键时可以为null,但只能存在一个
遍历集合中元素的方式
public static void main(String[] args) {
List<String> namelist = new ArrayList();
namelist.add("梨花");
namelist.add("云春");
namelist.add("冷湖");
namelist.add("林夕");
System.out.println("for循环");
for (int i = 0; i < namelist.size(); i++) {
String name = namelist.get(i);
System.out.println(name);
}
System.out.println("增强for循环");
for (String s : namelist) {
System.out.println(s);
}
System.out.println("迭代器循环");
Iterator<String> iterator = namelist.iterator();
while (iterator.hasNext())
{
String name = iterator.next();
System.out.println(name);
}
namelist.forEach(System.out::println);
}