Java异常类+常用类+容器、泛型
一 、Java异常类
1.认识异常
- 运行时异常RuntimeException
public class ExceptionTest1 {
public static void main(String[] args) {
//NumberFormatException
Integer.valueOf("abc");
//数组索引越界
int[] arr = {1,2,3};
System.out.println(arr[3]);
}
}
- 编译时异常
2.异常的处理
异常对象可以调用如下方法得到或输出有关异常的信息
public String getMessage();
public void printStackTrace();
public String toString();
捕获try-catch
直接捕获程序出现的异常,将可能出现的异常操作放在try-catch语句的try部分,一旦try部分抛出异常对象,或调用某个可能抛出异常对象的方法,并且该方法抛出了异常对象,try部分结束执行,转向执行相应的catch部分,程序可以将发生异常的处理放在catch部分。
try{
//监视可能出现异常的代码
}catch(异常类型一 变量){
//处理异常
}catch(异常类型二 变量){
//处理异常
}finally{
//无论如何要执行的语句
}
try{
//监视可能出现异常的代码
}catch(Exception e){
e.printStackTrace();//直接打印异常对象的信息
}//Exception代表可以捕获一切异常
import java.io.IOException;
public class Example1 {
public static void main(String[] args) {
int n=0,m=0,t=1000;
try {
m=Integer.parseInt("8888");
n=Integer.parseInt("ab89");//发生异常,转向catch
t=7777;//不执行
} catch (NumberFormatException e) {
System.out.println("发生异常:"+e.getMessage());//发生异常:For input string: "ab89"
}
System.out.println("n="+n+",m="+m+",t="+t);//n=0,m=8888,t=1000
try {
System.out.println("故意抛出I/O异常!");
throw new java.io.IOException("我是故意的");//故意抛出异常
} catch (java.io.IOException e) {
System.out.println("发生异常:"+e.getMessage());//发生异常:我是故意的
}
}
}
抛出throws
将方法内部出现的异常抛出去给调用者处理
方法 throws 异常一,异常二,异常三{
}
方法 throws Exception{
}//Exception代表可以捕获一切异常
1.内层的异常向外抛出,在最外层集中捕获异常,记录异常并响应合适的信息给用户
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//捕获异常,记录异常并响应合适的信息给用户
public class ExceptionTest2 {
public static void main(String[] args) {
try {
test();
} catch (Exception e) {
System.out.println("当前操作有问题");
e.printStackTrace();
}
}
public static void test() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse("2024-3-29 20:12");
System.out.println(d);
}
}
2.捕获异常,尝试重新修复
import java.util.Scanner;
//捕获异常,尝试修复
public class ExceptionTest3 {
public static void main(String[] args) {
while (true) {
try {
System.out.println(getScore());
} catch (Exception e) {
System.out.println("请输入合法的数字。");
}
}
}
public static int getScore(){
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入分数:");
int score = sc.nextInt();
if(score>=0&&score<=100){
return score;
}else{
System.out.println("您输入的分数是不合适的。");
}
}
}
}
3.自定义异常类
Java无法为全部问题都提供异常类来代表
- 自定义运行时异常,定义一个异常类继承RuntimeException;自定义编译时异常,定义一个异常类继承Exception
- 重写构造器
- 通过throw new异常类(×××)来创造异常对象并抛出
public class BankException extends Exception {
String message;
public BankException(int m,int n){
message = "入账金额"+m+"是负数或支出"+n+"是正数,不符合系统要求。";
}
public String warnMess(){
return message;
}
}
public class Bank {
private int money;
public void income(int in,int out) throws BankException{
if(in<=0||out>=0||in+out<=0){
throw new BankException(in,out);//方法抛出异常,导致方法结束
}
int netIncome = in+out;
System.out.printf("本次计算出的纯收入是:%d元\n",netIncome);
money=money+netIncome;
}
public int getMoney(){
return money;
}
}
import java.io.IOException;
public class Example {
public static void main(String[] args) {
Bank bank = new Bank();
try {
bank.income(200,-100);
bank.income(300,-100);
bank.income(400,-100);
System.out.printf("银行目前有%d元\n",bank.getMoney());
bank.income(200,100);
bank.income(99999,-100);
} catch (BankException e) {
System.out.println("计算收益的过程出现如下问题:");
System.out.println(e.warnMess());
}
System.out.printf("银行目前有%d元\n",bank.getMoney());
}
}
二 、常用类
1.包装类
包装类就是把基本类型的数据包装成对象。
基本数据类型 | 对应的包装类(引用数据类型) |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
bollean | Bollean |
- 自动装箱:基本数据类型可以自动转换为对应的包装类型
Integer i = 100;//Integer i = Integer.valueOf(100);
- 自动拆箱:包装类型可以自动转换为对应的基本数据类型
int num = i;//int num = i.intvalue();
字符串和基本数据类型相互转换
- 基本数据类型转换成字符串类型
1.Integer类:public static String toString(int i)
2.Integer类:public String toString()
3.String类:public static String valueof(int i)
- 字符串类型转换成基本数据类型
1.Integer类:public static int parseInt(String s)
2.Integer类:public static Integer valueof(String s)
public class Test {
public static void main(String[] args) {
//整数转化为字符串
int num = 100;
String s1 = Integer.toString(num);
Integer i =num;
String s2 = i.toString();
String s3 = String.valueOf(num);
//字符串转化为整数
String str = "100";
int i1 = Integer.parseInt(str);
int i2 = Integer.valueOf(str);
}
}
2.String类
String
String类被final修饰,不能被继承,默认其中所有的方法被fainal修饰,不能被重写。
String的本质是字符数组char[ ].
方法名 | 作用 |
---|---|
length() | 返回字符串长度 |
equals() | 判断是否相等 |
charAt(int index) | 返回指定索引位置的字符 |
indexOf(String str) | 找到返回起始下标,找不到返回-1 |
contains(CharSequence s) | 包含返回true,不包含返回false |
trim() | 返回字符串的副本,忽略前导和尾随空格 |
replace(char oldChar, char newChar) | 返回一个新的字符串,其中的所有oldChar字符都被替换为newChar |
replaceAll(String regex, String replacement) | 使用给定的替换字符串替换此字符串中匹配给定正则表达式的所有子字符串。 |
substring(int beginIndex) | 返回从指定位置开始到字符串结尾的子字符串。 |
substring(int beginIndex, int endIndex) | 返回从beginIndex到endIndex - 1的子字符串。 |
toUpperCase() | 将此字符串中的所有字符转换为大写。 |
toLowerCase() | 将此字符串中的所有字符转换为小写。 |
split(String regex) | 根据给定正则表达式的匹配拆分此字符串。 |
import java.util.Locale;
public class Test {
public static void main(String[] args) {
String s = "abcde";
int s1 = s.length();
System.out.println(s1);//5
boolean s2 = s.equals("abc");
System.out.println(s2);//false
char s3 = s.charAt(2);
System.out.println(s3);//c
int s4 = s.indexOf("bc");
System.out.println(s4);//1
boolean s5 = s.contains("abc");
System.out.println(s5);//true
String s6 = " abc ".trim();
System.out.println(s6.length());//3
String s7 = "abcabcabc".replace("bc","d");
System.out.println(s7);//adadad
String s8 = "abcde".substring(1,3);
System.out.println(s8);//bc
String s9 = "bac".toUpperCase();
System.out.println(s9);//BAC
String s10 = "张三,李四,王五";
String[] arr = s10.split(",");
for(String t : arr){
System.out.println(t);
}
//张三
//李四
//王五
}
}
StringBuilder和StringBuffer
StringBuilder代表可变字符串对象,比String更适合做字符串的修改工作
方法名称 | 说明 |
---|---|
public StringBuilder append(任意类型) | 添加数据并返回StringBuilder对象本身 |
public StringBuilder reverse() | 将对象的内容反转 |
public int length() | 返回对象内容长度 |
public String toString() | 通过toString可以实现把StringBuilder转换为String |
import java.util.Locale;
public class Test {
public static void main(String[] args) {
//创建一个空白的可变的字符串对象,不包含任何内容
StringBuilder s1 = new StringBuilder();
//创建一个指定字符串内容的可变字符串对象
StringBuilder s = new StringBuilder("abc");
//添加数据
s.append("de");
//支持链式编程
s.append(1).append(2).append(3);
System.out.println(s);
//反转
s.reverse();
System.out.println(s);
//返回字符串长度
System.out.println(s.length());
//转换为String
String rs=s.toString();
System.out.println(rs);
}
}
- StringBuffer用法和StringBuilder一样
- StringBuilder是线程不安全的,StringBuffer是线程安全的
3.BigDecimal
用于解决浮点运算时,出现结果失真的问题
构造器 public BigDecimal(String val)
方法名 | 说明 |
---|---|
public static BigDecimal valueof(double var) | 转换一个double成BigDecimal |
public BigDecimal add(BigDecimal b) | 加法 |
public BigDecimal subtract(BigDecimal b) | 减法 |
public BigDecimal multiply(BigDecimal b) | 乘法 |
public BigDecimal divide(BigDecimal b) | 除法 |
public BigDecimal add(BigDecimal b,精确位数,舍入模式) | 除法,可以控制精确到小数几位 |
public double doubleValue() | 将BigDecimal转换为Double |
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalDemo {
public static void main(String[] args) {
double a = 0.1;
double b = 0.3;
//BigDecimal a1 = new BigDecimal(Double.toString(a));
//BigDecimal b1 = new BigDecimal(Double.toString(b));
//小数先转换为字符串在转换为BigDecimal对象
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(b1);
System.out.println(c1);
BigDecimal c2 = a1.divide(b1,2, RoundingMode.HALF_UP);
System.out.println(c2);
double rs = c2.doubleValue();
System.out.println(rs);
}
}
三、容器、泛型
1.泛型简介
定义类、接口、方法时,同事声明了一个或多个类型变量(如:),把具体数据类型作为参数传递给类型变量,在编译阶段约束所能操作的数据类型。
泛型不支持基本数据类型,只支持对象数据类型(引用数据类型)。
泛型类
修饰符 class 类名<类型变量,类型变量,>{
}
泛型接口
修饰符 interface 接口名<类型变量,类型变量,>{
}
泛型方法
修饰符 <类型变量,类型变量,> 返回值类型 方法名(形参列表){
}
泛型的上下限:
上限:?extends Car ?接收的必须是Car类或者其子类
下限:?super Car ?接收的必须是Car类或者其父类
2. 列表
List系列集合特点:有序,可重复,有索引
List集合特有的方法
方法名称 | 说明 |
---|---|
void add(int index,E element) | 在此集合的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set (int index ,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(Int index) | 返回指定索引处的元素 |
import java.util.ArrayList;
import java.util.List;
public interface ListTest1 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("bbb");
list.add("ccc");
System.out.println(list);
list.add(2,"ddd");
System.out.println(list);
System.out.println(list.remove(2));
System.out.println(list.get(2));
System.out.println(list.set(3, "ddd"));
System.out.println(list);
}
}
ArrayList和LinkedList底层采用的数据结构不同,应用场景不同
-
ArrayList集合
基于数组实现:查询快,增删慢1.利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
2.添加第一个元素时,底层会创建一个新的长度为10的数组
3.存满时,会扩容1.5倍,如果一次添加多个元素,1.5倍还放不下,则创建数组的长度以实际为 准 -
LinkedList集合
基于双链表实现:查询慢,增删快,对首尾元素进行增删改查速度极快
LinkedList新增了对首尾操作的特有方法
方法名称 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 在该列表末尾插入指定的元素 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的一最后个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
可以用来设计队列(先进先出)、栈(先进后出)
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public interface ListTest1 {
public static void main(String[] args) {
//创建一个队列
LinkedList<Integer> queue = new LinkedList<>();
//入列
queue.addLast(1);
queue.addLast(2);
queue.addLast(3);
queue.addLast(4);
System.out.println(queue);//[1,2,3,4]
//出列
System.out.println(queue.removeFirst());//1
System.out.println(queue.removeFirst());//2
System.out.println(queue);//[3,4]
//创建一个栈
LinkedList<Integer> stack = new LinkedList<>();
//压栈(push)
stack.addFirst(1);
stack.addFirst(2);
stack.push(3);
stack.push(4);
System.out.println(stack);//[4,3,2,1]
System.out.println(stack.removeFirst());//4
System.out.println(stack.pop());//3
System.out.println(stack);//[2,1]
}
}
3.Set
Set系列集合特点:无序,不重复,无索引
- HashSet:无序,不重复,无索引
- LinkedHashSet:有序、不重复、无索引
- TreeSet:默认按照升序排序、不重复、无索引
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(3);
set.add(2);
set.add(1);
System.out.println(set);//[1,2,3]
Set<Integer> set1 = new LinkedHashSet<>();
set1.add(1);
set1.add(3);
set1.add(2);
set1.add(1);
System.out.println(set1);//[1,3,2]
Set<Integer> set2 = new TreeSet<>();
set2.add(1);
set2.add(3);
set2.add(2);
set2.add(1);
System.out.println(set2);//[1,2,3]
}
}
4.Map
认识Map集合
- Map集合称为双列集合
- 每个元素“key=value”称为一个键值对
- 键不允许重复,后面重复的数据会覆盖前面的数据,值可以重复,键和值一一对应,每个键只能找到自己对应的值
- HashMap:无序,不重复,无索引
- LinkedHashMap:有序、不重复、无索引
- TreeMap:默认按照升序排序、不重复、无索引
Map的常用方法
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapTest {
public static void main(String[] args) {
//1.添加元素
Map<String,Integer> map = new HashMap<>();
map.put("aaa",100);
map.put("aaa",200);
map.put("bbb",100);
map.put("ccc",200);
System.out.println(map);//{aaa=200, ccc=200, bbb=100}
//2.获取集合的大小
System.out.println(map.size());//3
//3.清空集合
//map.clear();
//System.out.println(map);//{}
//4.判断集合是否为空
System.out.println(map.isEmpty());//true
//5.根据键获取对应值
System.out.println(map.get("aaa"));//200
System.out.println(map.get("qqq"));//null
//6.根据键删除整个元素(返回键的值)
System.out.println(map.remove("ccc"));//200
System.out.println(map);//{aaa=200, bbb=100}
//7.判断是否包含某个键
System.out.println(map.containsKey("aaa"));//true
System.out.println(map.containsKey("ccc"));//false
//8.判断是否含有某个值
System.out.println(map.containsValue(100));//true
System.out.println(map.containsValue(300));//false
//9.获取Map集合的全部键
Set<String> keys = map.keySet();
System.out.println(keys);//[aaa, bbb]
//10.获取Map集合的全部值
Collection<Integer> values = map.values();
System.out.println(values);//[200, 100]
//11.把其他Map集合的数据导入到集合中来
Map<String,Integer> map2 = new HashMap<>();
map2.put("zzz",300);
map.putAll(map2);
System.out.println(map);//{aaa=200, bbb=100, zzz=300}
}
}
Map的遍历方式
- 键找值
- 键值对
- Lambda
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapTest {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("aaa", 100);
map.put("aaa", 200);
map.put("bbb", 100);
map.put("ccc", 200);
System.out.println(map);//{aaa=200, ccc=200, bbb=100}
//法一
Set<String> keys = map.keySet();
for (String key : keys) {
System.out.println(key + "->" + map.get(key));
/*aaa->200
ccc->200
bbb->100*/
}
//法二
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + "->" + entry.getValue());
/*aaa->200
ccc->200
bbb->100*/
}
//法三
map.forEach((k, v) -> {
System.out.println(k+"->"+v);
}); /*aaa->200
ccc->200
bbb->100*/
}
}