Stream流、异常体系

本文介绍了Java中不可变集合的概念、创建方法及其好处,详细阐述了Stream流的使用,包括流的获取、常用API及收集操作。此外,还深入探讨了异常处理体系,包括编译时异常和运行时异常的区别,以及如何处理异常以增强代码的稳定性和健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、创建不可变集合

1、不可变集合概述

  • 不可变集合,就是不可被修改的集合
  • 集合的数据项在创建的时候提供,并且在整个生命周期中都不可以改变,否则报错

2.为什么创建不可变对象

  • 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践
  • 或者当集合对象被不可信任的库调用时,不可变形式是安全的

3.如何创建不可变集合

  • 在List、Set、Map接口中,都存在of方法,可以创建一个不可变集合
  • 这个集合不能添加,不能删除,不能修改
public class CollectionDemo {
    public static void main(String[] args) {
        //1.不可变的List集合
        List<Double> lists=List.of(569.5,700.5,523.0,570.5);
        System.out.println(lists);//[569.5, 700.5, 523.0, 570.5]
      //  lists.add("345.5");不能添加
      //  lists.set(2,698.5);
        //System.out.println(lists);//不能修改
        Double d=lists.get(1);
        System.out.println(lists);//[569.5, 700.5, 523.0, 570.5]
        System.out.println(d);//700.5
        //2.不可变Set集合
       // Set<String> names=Set.of("小花","小白","小兰","小哈","小白");
       // System.out.println(names);//出现异常IllegalArgumentException不能重复
        Set<String> names=Set.of("小花","小白","小兰","小哈");
        //names.add("小明");
        //System.out.println(names);//UnsupportedOperationException不可以添加元素
        //3.不可变Map集合
        Map<String,Integer> maps=Map.of("huawei",2,"Java开发",1,"手表",1);
        System.out.println(maps);//{手表=1, huawei=2, Java开发=1}
        maps.put("HTML",12);
        System.out.println(maps);//UnsupportedOperationException不能添加元素
    }
}

二、Stream流

1.Stream的概述

1.1Stream流的概述
  • 在Java中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream流概念
  • 目的:用于简化集合和数组操作的API
1.2案例:体验Stream流的作用

在这里插入图片描述

public class StreamTest {
    public static void main(String[] args) {
        //初步体验Stream流的方便与快捷
        List<String> names=new ArrayList<>();
        Collections.addAll(names,"张小兰","张芳","张小花","小白","小花");
        System.out.println(names);
//        //1.将姓张的放在新集合
//        List<String> zhanglist=new ArrayList<>();
//        for(String name:names){
//            if(name.startsWith("张")){
//                zhanglist.add(name);
//            }
//        }
//        System.out.println(zhanglist);//[张小兰, 张芳, 张小花]
//        //2.找名称长度是3的张的姓名
//        List<String> zhangThreelist=new ArrayList<>();
//        for(String name:names){
//            if(name.startsWith("张")&&name.length()==3){
//                zhangThreelist.add(name);
//            }
//        }
//        System.out.println(zhangThreelist);//[张小兰, 张芳, 张小花]
        //3.使用Stream流实现
        names.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));
        //张小兰
        //张小花
    }
}

1.3Stream流的思想
  • 先得到集合或者数组的Stream流(就是一根传送带)
  • 把元素放上去
  • 然后就用这个Stream流简化的API来方便的操作元素

2.Stream流的获取

1.1Stream流的三类方法

1.1.1获取Stream流

  • 创建一条流水线,并把数据放到流水线上准备进行操作

1.1.2中间方法

  • 流水线上的操作,一次操作完毕之后,还可以继续进行其它操作

1.1.3终结方法

  • 一个Stream流只能有一个终结方法,是流水线上的最后一个操作
1.2集合获取Stream流的方式
  • 可以使用Collection接口中默认方法Stream()生成流
default Stream<E> stream()//获取当前集合对象的Stream流
1.3数组获取Stream流的方式
public static <T> Stream<T> stream (T[] array) //|获取当前数组的Stream流
public static<T> Stream<T> of(T...value)//获取当前数组/可变数据的Stream流

public class StreamDemo2 {
    public static void main(String[] args) {
        /**------------Collection集合获取Stream流---------------*/
        Collection<String> list=new ArrayList<>();
        Stream<String> s = list.stream();
        /**------------Map集合获取流------------------*/
        Map<String,Integer> maps=new HashMap<>();
        //键流
        Stream<String> keyStream=maps.keySet().stream();
        //值流
       Stream valuesStream= maps.values().stream();
        //键值对流
        Stream<Map.Entry<String, Integer>> stream = maps.entrySet().stream();
        /**-------------数组获取流--------------*/
        String[] names={"小花","小红","小包"};
        Stream<String> nameStream = Arrays.stream(names);
        Stream<String> nameStream2=Stream.of(names);
    }
         }

3.Stream流的常用API(中间操作方法)

在这里插入图片描述
在这里插入图片描述

public class StreamDemo3 {
    public static void main(String[] args) {
        /*
        目标:Stream流常用API
        forEach:逐一处理(遍历)
        count:统计个数
        ---- long count();
        filter :过滤元素
        ---- Stream<T> filter(Predicate<? super T>predicate)
        limit:取前几个元素
        skip:跳过前几个
        map:加工方法
        concat:合并流
        distinct:去重复
         */
        List<String> list=new ArrayList<>();
        list.add("张小花");
        list.add("小红");
        list.add("张小百");
        list.add("张包");
        list.add("张小兰");
      //  list.add("张小兰");
        list.add("小花");

        //Stream<T> filter(Predicate<? super T> predicate);
//        list.stream().filter(new Predicate<String>() {
//            @Override
//            public boolean test(String s) {
//                return s.startsWith("张");
//            }
//        });
        list.stream().filter( s-> s.startsWith("张")).forEach(s-> System.out.println(s));
        //张小花
        //张小百
        //张包
        //张小兰
        list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));
        //张小花
        //张小百
        //张小兰
        long size = list.stream().filter(s -> s.length() == 3).count();
        System.out.println(size);//3
   //     list.stream().filter(s->s.startsWith("张")).limit(2).forEach(s-> System.out.println(s));
        list.stream().filter(s->s.startsWith("张")).limit(2).forEach(System.out::println);//上行代码的简化

        //张小花
        //张小百
        list.stream().filter(s->s.startsWith("张")).skip(2).forEach(s-> System.out.println(s));
       //张包
       //张小兰
        //Map加工方法
        //给集合元素的前面都加上一个:开心的
//        list.stream().map(new Function<String, String>() {
//            @Override
//            public String apply(String s) {
//                return "开心的"+s;
//            }
//        });
        //map加工方法:第一个参数原材料,->第二个参数是加工后的结果
        list.stream().map(s-> "开心的"+s).forEach(s-> System.out.println(s));
        //list.stream().map(Student::new Student).forEach(System.out::println);//上一行代码简化   构造器引用   方法引用
        //开心的张小花
        //开心的小红
        //开心的张小百
        //开心的张包
        //开心的张小兰
        //开心的小花
        //需求:把所有的名称都加工成一个学生对象
        //1.创建学生类对象
        /*
        public class Student {
    private String name;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}
         */
        list.stream().map(s->new Student(s)).forEach(s-> System.out.println(s));
        //Student{name='张小花'}
        //Student{name='小红'}
        //Student{name='张小百'}
        //Student{name='张包'}
        //Student{name='张小兰'}
        //Student{name='小花'}
        //concat合并流
        Stream<String> s1=list.stream().filter(s->s.startsWith("张"));
        Stream<String> s2= Stream.of("Java1","Java2");
      //  public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
        Stream<String> s3= Stream.concat(s1,s2);
        s3.forEach(s-> System.out.println(s));
        //张小花
        //张小百
        //张包
        //张小兰
        //Java1
        //Java2
        
      //  list.stream().distinct().forEach(s-> System.out.println(s));
        //张小花
        //小红
        //张小百
        //张包
        //张小兰
        //小花
    }
}

注意:

  • 中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程
  • 在Stream流中无法直接修改集合,数组中的数据

4.Stream流的综合应用

在这里插入图片描述

public class StreamDemo4 {
    public static double allMoney;
    public static double allMoney2;
    public static double allMoney3;


    public static void main(String[] args) {
        List<Employee> one=new ArrayList<>();
        one.add(new Employee("小红",'女',30000,25000,null));
        one.add(new Employee("小明",'男',25000,1000,"顶撞上司"));
        one.add(new Employee("小蓝",'女',20000,20000,null));
        one.add(new Employee("小白",'男',20000,25000,null));
        List<Employee> two=new ArrayList<>();
        two.add(new Employee("明明",'女',15000,9000,null));
        two.add(new Employee("红红",'男',20000,10000,null));
        two.add(new Employee("白白",'女',50000,100000,"被打"));
        two.add(new Employee("兰兰",'女',3500,1000,"被打"));
        two.add(new Employee("天天",'男',20000,0,"打人"));
        //1.开发1部门的最高工资的员工
        //指定大小规则
//        Employee e=one.stream().max(( o1,  o2)-> Double.compare(o1.getSalary()+o1.getBonus(),o2.getSalary()+o2.getSalary())).get();
//        //Employee{name='小红', sex=女, salary=30000.0, bonus=25000.0, punish='null'}
//        System.out.println(e);
        Topperformer t = one.stream().max((o1, o2) -> Double.compare(o1.getSalary() + o1.getBonus(), o2.getSalary() + o2.getSalary())).map(e -> new Topperformer(e.getName(), e.getBonus() + e.getSalary())).get();
        System.out.println(t);
        //Topperformer{name='小红', money=55000.0}
        //2.开发2部门的最高工资的员工
        Topperformer t2=two.stream().max((o1, o2) -> Double.compare(o1.getSalary() + o1.getBonus(), o2.getSalary() + o2.getSalary())).map(e -> new Topperformer(e.getName(), e.getBonus() + e.getSalary())).get();
        System.out.println(t2);
        //Topperformer{name='白白', money=150000.0}
        //3.分别统计两个部门的平均工资,去掉最高工资和最低工资
//       one.stream().sorted(new Comparator<Employee>() {
//           @Override
//           public int compare(Employee o1, Employee o2) {
//               return Double.compare(o1.getSalary()+o1.getBonus(),o2.getSalary()+o2.getBonus());
//           }
//       });

        one.stream().sorted(( o1,  o2)-> Double.compare(o1.getSalary()+o1.getBonus(),o2.getSalary()+o2.getBonus())).skip(1).limit(one.size()-2).forEach(s-> {
            //求出总和:剩余员工的工资总和
            allMoney+=(s.getBonus()+s.getSalary());
        });
        //开发一部的平均工资是多少
        System.out.println("开发一部的平均工资是:"+allMoney/(one.size()-2));//开发一部的平均工资是:42500.0
        开发一部的平均工资是:42500.0
        two.stream().sorted((o1,o2)->Double.compare(o1.getSalary()+o1.getBonus(),o2.getSalary()+o2.getBonus())).skip(1).limit(two.size()-3).forEach(s->{
            //求出总和,剩余员工的工资总和
            allMoney2+=(s.getBonus()+s.getSalary());
        });
        System.out.println("开发二部的平均工资是:"+allMoney2/(one.size()-3));
        //开发二部的平均工资是:44000.0
        //4.合并两个流集合,再统计
        Stream<Employee> s1=one.stream();
        Stream<Employee> s2=two.stream();
        Stream<Employee> s3 = Stream.concat(s1, s2);
        s3.sorted(( o1,  o2) -> Double.compare(o1.getSalary()+o1.getBonus(),o2.getSalary()+o2.getBonus())).skip(1).limit((one.size()+two.size())-2).forEach(s->{
            allMoney3+=s.getBonus()+s.getSalary();
        });
        //BigDecimal
        BigDecimal a=BigDecimal.valueOf(allMoney3);
        BigDecimal b=BigDecimal.valueOf((one.size()+two.size())-2);
        System.out.println("开发部的平均工资为:"+a.divide(b,2, RoundingMode.HALF_UP));
        //开发部的平均工资为:34285.71
    }
}

5.收集Stream流

5.1Stream流的收集操作
  • 收集
  • Stream流的含义:把Stream流操作后的结果数据转回到集合或者数组中去
  • Stream流:方便操作集合/数组的手段
  • 集合/数组:才是开发中的目的
5.2Stream流的收集方法

在这里插入图片描述

public class StreamDemo5 {
    /**
     * 目标:收集Stream流的数据到集合或者数组中去
     */
    public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        list.add("张小花");
        list.add("小红");
        list.add("张小百");
        list.add("张包");
        list.add("张小兰");
        list.add("小花");
        Stream<String> stream =list.stream().filter(s->s.startsWith("张"));
        //List<String> zhangLists=stream.collect(Collectors.toList());
        List<String> zhangLists=stream.toList();//得到不可变集合
        System.out.println(zhangLists);//[张小花, 张小百, 张包, 张小兰]
        //注意:流只能使用一次
        Stream<String> stream2 =list.stream().filter(s->s.startsWith("张"));
        Set<String> zhangSets=stream2.collect(Collectors.toSet());
        System.out.println(zhangSets);//[张小兰, 张小花, 张包, 张小百]
        Stream<String> stream3 =list.stream().filter(s->s.startsWith("张"));
//        Object[] s = stream3.toArray();
//        String[] s = stream3.toArray(new IntFunction<String[]>() {
//            @Override
//            public String[] apply(int value) {
//                return new String[value];
//            }
//        });
        String[] s = stream3.toArray(value->new String[value]);
        System.out.println("数组内容:"+Arrays.toString(s));//数组内容:[张小花, 张小百, 张包, 张小兰]
    }
}


三、异常处理

1.异常概述、体系

1.1异常的概述
  • 异常是程序在“编译”或者“执行”过程中可能出现的问题,注意:语法错误不算在异常体系中
  • 异常一旦出现,如果没有提前处理,程序就会退出JVM虚拟机而终止
  • 研究异常并且避免异常,然后提前处理异常,体现的是程序的安全、健壮性
1.2异常体系

在这里插入图片描述

1.2编译时异常和运行时异常

在这里插入图片描述

2.常见运行时异常

2.1运行时异常
  • 直接继承RuntimeException或者其子类,编译阶段不会报错,运行时可能出现错误
2.2运行时异常示例
  • 数组索引越界异常ArrayIndexOutOfBoundsException
  • 空指针异常NullPointerException
  • 数字操作异常ArithmeticException
  • 类型转换异常ClassCastException
  • 数字转换异常NumberFormatException
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。。。。。。。。");
        //1.数组索引越界异常ArrayIndexOutOfBoundsException
        int[] arr={1,2,3};
        System.out.println(arr[2]);
       // System.out.println(arr[3]);//运行出错,程序终止ArrayIndexOutOfBoundsException
        //2. 空指针异常NullPointerException
        String name=null;
        System.out.println(name);
       // System.out.println(name.length());//运行出错,程序终止NullPointerException
        //3.类型转换异常
        Object o=23;
        //String s=(String)o;//ClassCastException
        //4.数字操作异常ArithmeticException
       // int c=10/0;//ArithmeticException
        //5.数字转换异常NumberFormatException
//        String number="23";
//        Integer it=Integer.valueOf(number);
//        System.out.println(it+1);//24
        String number="23aabb";
        Integer it=Integer.valueOf(number);//NumberFormatException
    }
}

3.常见编译时异常

3.1编译时异常
  • 不是RuntimeException或者其子类的异常,编译阶段就报错,必须处理,否则代码不通过
3.2编译时异常案例
  • 日期解析日常:ParseException
public class ExceptionDemo {
    public static void main(String[] args) throws ParseException {
        String date = "2015-01-12 10:23:21";
        //创建一个简单日期格式化类:解析字符串时间成为日期对象
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d=sdf.parse(date);//ParseException
        System.out.println(d);
    }
}
3.3编译时异常的作用
  • 担心程序员的技术不行,在编译阶段就报出一个错误,目的在于提醒不要出错!

4.异常的默认处理流程

public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("程序开始");
        chu(10,0);
        //程序开始
        //10
        //0
        //Exception in thread "main" java.lang.ArithmeticException: / by zero
        //	at com.itheima.d6_exception_default.ExceptionDemo.chu(ExceptionDemo.java:12)
        //	at com.itheima.d6_exception_default.ExceptionDemo.main(ExceptionDemo.java:6)
        System.out.println("程序结束");
    }
    public static void chu(int a,int b){
        System.out.println(a);
        System.out.println(b);
        int c=a/b;
        System.out.println(c);
    }
}
  • 默认异常处理机制并不好,一旦真的出现异常,程序立即死亡

5.编译时异常的处理机制

5.1编译型异常得处理形式有三种:
  • 出现异常直接抛给调用者,调用者也可以继续抛出去
  • 出现异常自己捕获,不麻烦别人
  • 前两者的结合,出现异常直接抛出去给调用者,调用者捕获处理
5.2异常处理方式1:throws
  • throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理
  • 这种方法并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡
//抛出异常格式:
方法 throws 异常1,异常2,异常3..{
}
public class ExceptionDemo01 {
    public static void main(String[] args) throws ParseException, FileNotFoundException {
        System.out.println("程序开始");
        parseTime("2011-11-11 11:11:11");
        System.out.println("程序结束");
    }
    public static void parseTime(String date) throws ParseException, FileNotFoundException {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d=sdf.parse(date);
        System.out.println(d);
        
        InputStream is=new FileInputStream("C:/mei.jpg");
    }
}

//规范做法
方法 throws Exception{

}
public class ExceptionDemo01 {
    public static void main(String[] args) throws Exception {
        System.out.println("程序开始");
        parseTime("2011-11-11 11:11:11");
        System.out.println("程序结束");
    }
    public static void parseTime(String date) throws Exception {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d=sdf.parse(date);
        System.out.println(d);

        InputStream is=new FileInputStream("C:/mei.jpg");
    }
}
5.3异常处理方式2:try…catch…
  • 监视捕获异常,用在方法内部,可以将饭不够发内部出现的异常直接捕获处理
  • 这种方法还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行
//格式
try{
//监视可能出现异常的代码
}catch(异常类型1 变量1){
//处理异常
}catch(异常类型2 变量2){
//处理异常
}
public class ExceptionDemo02 {
        public static void main(String[] args)  {
            System.out.println("程序开始");
            parseTime("2011-11-11 11:11:11");
            System.out.println("程序结束");
            //程序开始
            //Fri Nov 11 11:11:11 CST 2011
            //你的文件不存在
            //程序结束
        }
        public static void parseTime(String date)  {
            try {
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date d=sdf.parse(date);
                System.out.println(d);
            } catch (ParseException e) {
                //解析出现的问题
                System.out.println("出现了解析时间异常哦,走点心");
            }
            try {
                InputStream is=new FileInputStream("C:/mei.jpg");
            } catch (FileNotFoundException e) {
                System.out.println("你的文件不存在");
            }
        }
    }
public class ExceptionDemo02 {
        public static void main(String[] args)  {
            System.out.println("程序开始");
            parseTime("2011-11-11 11:11:11");
            System.out.println("程序结束");
//            程序开始
//            java.text.ParseException: Unparseable date: "2011-11-11 11:11:11"
//            at java.base/java.text.DateFormat.parse(DateFormat.java:399)
//            at com.itheima.d7_exception_handle.ExceptionDemo02.parseTime(ExceptionDemo02.java:21)
//            at com.itheima.d7_exception_handle.ExceptionDemo02.main(ExceptionDemo02.java:12)
//            程序结束
        }
        public static void parseTime(String date)  {
            try {
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy、-MM-dd HH:mm:ss");
                Date d=sdf.parse(date);
                System.out.println(d);
                InputStream is=new FileInputStream("C:/mei.jpg");
            } catch (ParseException e) {
                //解析出现的问题
                e.printStackTrace();//打印异常栈信息
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
//官方建议:
public class ExceptionDemo02 {
        public static void main(String[] args)  {
            System.out.println("程序开始");
            parseTime("2011-11-11 11:11:11");
            System.out.println("程序结束");
//            程序开始
//            java.text.ParseException: Unparseable date: "2011-11-11 11:11:11"
//            at java.base/java.text.DateFormat.parse(DateFormat.java:399)
//            at com.itheima.d7_exception_handle.ExceptionDemo02.parseTime(ExceptionDemo02.java:21)
//            at com.itheima.d7_exception_handle.ExceptionDemo02.main(ExceptionDemo02.java:12)
//            程序结束
        }
        public static void parseTime(String date)  {
            try {
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy、-MM-dd HH:mm:ss");
                Date d=sdf.parse(date);
                System.out.println(d);
                InputStream is=new FileInputStream("C:/mei.jpg");
            } catch (Exception e) {
                //解析出现的问题
                e.printStackTrace();//打印异常栈信息
            } 
        }
    }
5.4异常处理方式3:前两者结合
  • 方法直接将异常通过throws抛出去给调用者
  • 调用者收到异常后直接捕获处理
public class ExceptionDemo03 {
        public static void main(String[] args)  {
            System.out.println("程序开始");
            try {
                parseTime("2011-11-11 11:11:11");
                System.out.println("功能操作成功");
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("操作失败");
            }
            System.out.println("程序结束");
        }
        public static void parseTime(String date) throws Exception {
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date d=sdf.parse(date);
                System.out.println(d);
                InputStream is=new FileInputStream("C:/mei.jpg");
            }
        }

6.运行时异常的处理机制

  • 运行时异常编译阶段不会出错,是运行时才会出错,所以编译阶段不处理也可以
  • 按照规范建议还是处理:建议在最外层调用处理集中捕获处理即可
//目标:运行时异常的处理机制
//可以不处理编译阶段不会报错
//按照理论规则:建议还是处理,只需要在最外层捕获处理
public class Test {
    public static void main(String[] args) {
        System.out.println("程序开始");
        try {
            chu(10,0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //程序开始
    //10
    //0
    //java.lang.ArithmeticException: / by zero
    //	at com.itheima.d8_exception_handle_runtime.Test.chu(Test.java:17)
    //	at com.itheima.d8_exception_handle_runtime.Test.main(Test.java:9)
    public static void chu(int a,int b){//throws RunException
        System.out.println(a);
        System.out.println(b);
        int c=a/b;
        System.out.println(c);
    }
}

7.异常处理使代码更稳健的案例

需求

  • 键盘录入一个合理的几个为止(必须是数值,值必须大于0)

分析

  • 定义一个死循环,让用户不断地输入价格
public class Test2 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        while(true){
            try {
                System.out.println("请您输入合法的价格:");
                //请您输入合法的价格:
                //345jjj
                //请您输入合法的数值,建议为正数
                //请您输入合法的价格:
                //45
                //定价:45
                String priceStr=sc.nextLine();
                //转换为Double类型的数据
                double price=Double.valueOf(priceStr);
                if(price>0){
                    System.out.println("定价:"+priceStr);

                    break;
                }else{
                    System.out.println("价格必须是正数");
                }
            } catch (NumberFormatException e) {
                System.out.println("请您输入合法的数值,建议为正数");
            }
        }
    }
}

8.自定义异常

8.1自定义异常的必要
  • java无法为全部问题提供异常类
  • 如果企业想通过异常的方式来管理自己的某个业务,就需要自定义异常类
8.2自定义异常的好处
  • 可以使用异常机制管理业务问题,如提醒程序员注意
  • 同时一旦出现bug,可以用异常的形式清晰的指出出错的地方
8.3自定义异常的分类
1.自定义编译异常
  • 定义一个异常类继承Exception
  • 重写构造器
  • 在出现异常的地方用throw new自定义对象抛出
/**
 * 自定义编译异常
 * 1.继承Exception
 * 2.重写构造器
 */
public class ItheimaAgeIlleagalException extends Exception{
    public ItheimaAgeIlleagalException() {
    }
    public ItheimaAgeIlleagalException(String message) {
        super(message);
    }
}
public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            checkAge(34);
        } catch (ItheimaAgeIlleagalException e) {
           e.printStackTrace();
        }
    }
    public static void checkAge(int age) throws ItheimaAgeIlleagalException {
        if(age<0||age>200){
            //抛出一个异常对象给调用者
            //throw:在方法内部直接创建一个异常对象,并从此点抛出
            //throws:用在方法声明上面,抛出方法内部的异常
            throw new ItheimaAgeIlleagalException(age + "is illeagal");
        }else{
            System.out.println("年龄合法:推荐商品给其购买");
        }
    }
}
  • 作用:编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理
2.自定义运行异常
  • 定义一个异常类继承RunException
  • 重写构造器
  • 在出现异常的地方用throw new自定义对象抛出

作用:提醒不强烈,编译阶段不报错,运行时才可能出现

/**
 * 自定义编译时异常
 * 1.继承RunException
 * 2.重写构造器
 */
public class ItheimaIlleagalRunException extends RuntimeException{
    public ItheimaIlleagalRunException() {
    }

    public ItheimaIlleagalRunException(String message) {
        super(message);
    }
}
public class ExceptionDemo {
    public static void main(String[] args) {
//        try {
//            checkAge(34);
//        } catch (ItheimaAgeIlleagalException e) {
//           e.printStackTrace();
//        }
        try {
            checkAge2(-34);
        } catch (Exception e) {
           e.printStackTrace();
        }
    }
    public static void checkAge2(int age)  {
        if(age<0||age>200){
            //抛出一个异常对象给调用者
            //throw:在方法内部直接创建一个异常对象,并从此点抛出
            //throws:用在方法声明上面,抛出方法内部的异常
            throw new ItheimaIlleagalRunException(age + "is illeagal");
        }else{
            System.out.println("年龄合法:推荐商品给其购买");
        }
    }
    public static void checkAge(int age) throws ItheimaAgeIlleagalException {
        if(age<0||age>200){
            //抛出一个异常对象给调用者
            //throw:在方法内部直接创建一个异常对象,并从此点抛出
            //throws:用在方法声明上面,抛出方法内部的异常
            throw new ItheimaAgeIlleagalException(age + "is illeagal");
        }else{
            System.out.println("年龄合法:推荐商品给其购买");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值