• Java 异常处理机制和集合框架


    一、实验目的

    掌握面向对象程序设计技术

    二、实验环境

    1微型计算机一台 

    2WINDOWS操作系统,Java SDK,Eclipse开发环境

    三、实验内容 

    1、Java异常处理机制涉及5个关键字:try、catch、finally、throw、throws,请理解每个关键字的作用,并在编写程序,使用运用这5个关键字,观察效果。

    2、设计学生类(是一个javaBean),包含年龄和姓名(均私有)。

    3、Java常用的集合类有:HashSet、TreeSet(红黑树)、ArrayList、Stack、HashMap(用学生类的年龄作为键值)、Properties,请编写程序,分别使用运用这些集合类,来存储学生类对象。

    4、请问java中有没有优先队列实现类,如果有,请编写程序,演示该类的使用。

    四、实验步骤和结果

    1、Java异常处理机制涉及5个关键字:try、catch、finally、throw、throws,请理解每个关键字的作用,并在编写程序,使用运用这5个关键字,观察效果。

    (1)try和catch

    try的意思是测试它所包含的代码是否会发生异常,而catch 的意思就是在异常发生时就抓住它,并进行相应的处理,使程序不受该异常的影响从而继续执行下去。

    它们通常使用的格式如下:

    Try{
      //代码段(可能会发生异常的代码)
    } catch (异常类型 ex) {
      //对异常进行处理的代码段
    }
    //代码段

    测试代码(MoreCatchDemo.java)如下所示:(注意:当有多个catch,在安排catch语句的顺序时,首先应该捕获子类异常,然后再捕获父类异常)

    import java.util.InputMismatchException;
    import java.util.Scanner;
    public class MoreCatchDemo {
    /*** @param args */
    public static void main(String[] args) {
    Scanner in=new Scanner(System.in);
    try {
       System.out.println("请输入第一个学期的总学时:");
      int totalTime=in.nextInt();//总学时
      System.out.println("请输入第一个学期的总课程:");
      int totalCourse=in.nextInt();//课程总数
      System.out.println("第一学期各个课程的平均学时为:"+totalTime/totalCourse);
    } catch (InputMismatchException e1) {
      // TODO: handle exception
      System.out.println("输入不为数字!");
    }catch (ArithmeticException e2) {
      // TODO: handle exception
      System.out.println("课程数目不能为0!");
    }catch (Exception e) {
      // TODO: handle exception
      System.out.println("发生错误:"+e.getMessage());
    }
      System.out.println("我是catch后面的代码。");
    }
    }

    (2) finally

       在某些特定的情况下,不管是否有异常发生,总是要求某些特定的代码必须被执行,这就需要用到finally 关键字。

    测试代码(FinallyDemo.java)如下所示:

    public class FinallyDemo {
    /**  * @param args */
      public static void main(String[] args) {、
      System.out.println("请打开数据连接……");、
      try {
        System.out.println("执行查询操作");
        System.out.println("执行修改操作");
        int i=12/0;
        System.out.println("执行添加操作");
        System.out.println("执行删除操作");
    } catch (Exception e) {
        // TODO: handle exception
         System.out.println("除零出错!");
        e.printStackTrace();
    }  finally{
      System.out.println("请关闭数据连接……");
    }
    }
    }

    (3)throw

          throw 语句用来明确地抛出一个“异常”。需要注意的是,用户必须得到一个Throwable类或者其他子类产生的实例句柄,通过参数传到catch字句,或者用 new语句来创建一个实例。throw 总是出现在函数体中,用来抛出一个异常。程序会在throw语句后立即终止,它后面的语句执行不到,throw后必须抛出一个Throwable类的实例。

    测试代码(ThrowDemo.java)如下所示:

    public class ThrowDemo {
       /**  * @param args  */
      public static void main(String[] args) {
      // TODO Auto-generated method stub
      int number=0;
      try {、
      number=Integer.parseInt(args[0]);
       } catch (Exception e) {
        // TODO: handle exception
        throw new ArrayIndexOutOfBoundsException("数组越界!");
        //System.out.println("非法的数字");
    }、
        System.out.println("你输入的数字为:"+number);
    }
    }

    (4)throws

      Throws 用来声明一个方法可能会抛出的所有异常,它跟在方法签名的后面。

    若这个方法可以引发异常,而它本身并不对该异常进行处理,那么该方法必须将这个异常抛给调用者以使程序能够继续执行下去。如果有多个异常,则使用逗号将其分开。

    测试代码(ThrowsDemo.java)如下所示:

    public class ThrowsDemo {
    /**  * @param args*/  
    public static void main(String[] args) {
    testThrows(args);
    }
    private static void testThrows(String[] tmp) {
    try {
    createThrow(tmp);
    } catch (Exception e) {
    System.out.println("来自createThrow方法的异常");
    }
    }
    //抛出可能的异常
    private static void createThrow(String[] tmp) throws Exception {
    int number=3;
    System.out.println("你输入的数字为:"+number+'
    ');
    number=Integer.parseInt(tmp[0]);
    System.out.println("你输入的数字为:"+number);
    }
    }

    (5)throw和throws语句的组合使用

        一般都需要throw和throws语句的组合使用,就是在捕获异常后,抛出一个明确的异常给调用者。

    测试代码(ThrowAndThrowsDemo.java)如下所示:

    public class ThrowAndThrowsDemo {
    /*** @param args*/
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    testThrow(args);
    }
         //调用有异常的方法
    private static void testThrow(String[] tmp) {
    // TODO Auto-generated method stub
    try {
    createThrow(tmp);
    } catch (Exception e) {
    System.out.println("捕捉来自createThrow方法的异常");
    }
    }
        //抛出一个具体的异常
    private static void createThrow(String[] tmp) throws Exception {
    // TODO Auto-generated method stub
    int number=0;
    try {
    number=Integer.parseInt(tmp[0]);
    } catch (Exception e) {
    // TODO: handle exception
    throw new ArrayIndexOutOfBoundsException("数组越界");
    }
    System.out.println("你输入的数字为:"+number);
    }
    }

    2、设计学生类(是一个javaBean),包含年龄和姓名(均私有)。

    测试代码(StudentJavaBean.java)如下所示:

    //StudentJavaBean:
    //1.有一个无参的公共的构造方法
    //2.有属性,属性最好定义为私有的。
    //3.有与属性对应的get、set存取方法
    //public class StudentJavaBean implements Comparable {  //在实现TreeSetTest中,这里接口是必须的
    public class StudentJavaBean  { 
          private int age;
          private String name;
          private Integer score;
     public StudentJavaBean() {  } //无参构造方法
          public StudentJavaBean(int age, String name,int score) {
    super();
    this.age = age;
    this.name = name;
    this.score=score;
    }
    //与属性对应的get、set存取方法
      public String getName() {
    return name;
      }
      public void setName(String name) {
    this.name = name;
    }
     public Integer getAge() {
    return age;
    }
     public void setAge(Integer age) {
    this.age = age;
    }
     public Integer getScore() {
    return score;
    }
    public void setScore(Integer score) {
    this.score = score;
    }
     //要显示Student的信息,必须重写toString()方法
     public String toString() {
    return "StudentJavaBean [age=" + age + ", name=" + name +",score="+ score+ "]";
    }

    3、Java常用的集合类有:HashSet、TreeSet(红黑树)、ArrayList、Stack、HashMap(用学生类的姓名作为键值)、Properties,请编写程序,分别使用运用这些集合类,来存储学生类对象。

    (1)HashSet

    测试代码(HashSetTest.java)如下所示:

    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    public class HashSetTest {
    /** @param args */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    HashSet hs=new HashSet();
    hs.add(new StudentJavaBean(19,"张三",80));
    hs.add(new StudentJavaBean(18,"李四",90));
    hs.add(new StudentJavaBean(20,"黄七",85));
    hs.add(new StudentJavaBean(17,"王五",95));
    hs.add(new StudentJavaBean(21,"赵六",88));
    Iterator it=hs.iterator();//获取集合迭代器
    while (it.hasNext()) {
    System.out.println(it.next());//HashSet不保存元素加入顺序的特征
    }
    }
    }、

    (2)TreeSet

    测试代码(TreeSetTest.java)如下所示:

    import java.util.Iterator;
    import java.util.Set;
    import java.util.TreeSet;
    import java.util.*;
    public class TreeSetTest {
    /** * @param args */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    Set<StudentJavaBean> ts=new TreeSet<StudentJavaBean>();
    StudentJavaBean stu1=new StudentJavaBean(18,"张三",78);
    StudentJavaBean stu2=new StudentJavaBean(23,"李四",79);
    StudentJavaBean stu3=new StudentJavaBean(32,"王五",80);
    StudentJavaBean stu4=new StudentJavaBean(21,"赵六",87);
    StudentJavaBean stu5=new StudentJavaBean(18,"黄七",89);
    ts.add(stu3);
    ts.add(stu4);
    ts.add(stu1);
    ts.add(stu2);
    //ts.add(null);//不可以有null ? 会出错!!
    Iterator it=ts.iterator();
    while (it.hasNext()) {
    System.out.println(it.next());
    }
    }
    }

    同时,Student类要实现一个 Comparable接口,

    修改之后代码如下:

    public class StudentJavaBean implements Comparable {//在实现TreeSetTest中,这里接口是必须的
    //public class StudentJavaBean  { 
          private int age;
          private String name;
          private Integer score;
      public StudentJavaBean() {  } //无参构造方法
          public StudentJavaBean(int age, String name,int score) {
    super();
    this.age = age;
    this.name = name;
    this.score=score;
    }
    //与属性对应的get、set存取方法
      public String getName() {
    return name;
      }
      public void setName(String name) {
    this.name = name;
    }
     public Integer getAge() {
    return age;
    }
     public void setAge(Integer age) {
    this.age = age;
    }
     public Integer getScore() {
    return score;
    }
    
    public void setScore(Integer score) {
    this.score = score;
    }
     //要显示Student的信息,必须重写toString()方法
     public String toString() {
    return "StudentJavaBean [age=" + age + ", name=" + name +",score="+ score+ "]";
    }
    
    //在Java规范要求中,如果用户重写了equals()方法,就一定要重写hashCode()方法
    //两个对象进行equals比较时,如果返回true,那么它们的hashCode要求返回相等的值
    public int hashCode() {
    return age*name.hashCode();
    }
    
    //HashSet 中加入的对象需要重写hashCode()和equals()方法
    public boolean equals(Object o) {
    StudentJavaBean s=(StudentJavaBean) o;
    return age==s.age && name.equals(s.name);
    }
    
    //“让StudentJavaBean类实现Comparable接口”
        //因为要实现 Comparable接口,所以要重写comparaTo(object o)方法
    //判断执行comparaTo方法的Student对象与传入的对象按排序的条件相比,
    //是大于、小于还是等于传入的对象
    public int compareTo(Object o) {
    StudentJavaBean s=(StudentJavaBean) o;
    if (s.getAge() < this.getAge()) 
    return 1;
    else if(s.getAge() == this.getAge())
    return 0;
    else 
    return -1;
    }
    //其实Integer 已经实现了Comparable接口,所以这里的compareTo方法中的代码还可以这样写:
    // public int  comparaTo(Object o) {
    // StudentJavaBean s=(StudentJavaBean )o;
    // return s.age.compareTo(this.age);// }

    自定义比较器的代码(SelfTreeSetTest.java)如下:

    import java.util.*;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.TreeSet;
    import java.util.LinkedHashSet;
    import java.util.Comparator;
    //学生年龄比较器                     //下面这个借口指明参与比较的两个对象是学生类
    class StudentAgeComparator implements Comparator<StudentJavaBean>{
    public int compare(StudentJavaBean o1, StudentJavaBean o2) {
    // TODO Auto-generated method stub
    int i=o2.getAge() - o1.getAge();
    return i; }}
    //学生成绩比较器  
    class StudentScoreComparator implements Comparator<StudentJavaBean> {
    public int compare(StudentJavaBean o1, StudentJavaBean o2) {
    int i=(int)(o2.getScore() - o1.getScore());
    return i; }}
    public class SelfTreeSetTest {
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    //创建TreeSet对象时选择比较器
    //Set<StudentJavaBean> ts=new TreeSet<StudentJavaBean>(new StudentAgeComparator());
    //上面是选择年龄比较器,下面是选择分数比较器
    Set<StudentJavaBean> ts=new TreeSet<StudentJavaBean>(new StudentScoreComparator());
    StudentJavaBean stu1=new StudentJavaBean(18,"张三",99);
    StudentJavaBean stu2=new StudentJavaBean(19,"李四",95);
    StudentJavaBean stu3=new StudentJavaBean(20,"王五",90);
    StudentJavaBean stu4=new StudentJavaBean(21,"赵六",94);
    ts.add(stu3);
    ts.add(stu4);
    ts.add(stu1);
    ts.add(stu2);
    Iterator it=ts.iterator();
    while (it.hasNext()) {    System.out.println(it.next()); } }}

    (3)ArrayList

    测试代码( ListDemo.java)如下所示:

    import java.awt.List;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    public class ListDemo {
    /**  * @param args  */
    public static void main(String[] args) {
    Collection c1=new ArrayList();
    c1.add(new Student(20,"张三"));
    Student c3=new Student(22,"王五");
    c1.add(c3);
    c1.add(new Student(19,"黄七"));
    System.out.println("c1:"+c1);
    Collection c2=new ArrayList();
    c2.addAll(c1);//将集合c1添加到c2集合对象中的操作
    System.out.println("c2:"+c2);
    c2.remove(c3);//删除一个学生
    System.out.println("c2:"+c2);
    c2.add("hello");//添加
    System.out.println("c2:"+c2);
    Iterator it=c2.iterator();//下面介绍迭代器接口
    while (it.hasNext()) { //用迭代器进行迭代(遍历)操作
    Object obj=it.next(); //取出的元素类型为Object类型
    System.out.println("Iterator遍历c2 "+obj+"	");
    }
    }
    }

    (4)Stack

    测试代码(ThrowAndThrowsDemo.java)如下所示:

    import java.util.Stack;
    public class StackDemo {
    /**  * @param args  */
    public static void main(String[] args) {
    Stack stk=new Stack();//创建一个空Stack
    stk.push(new Student(19,"张三"));
    stk.push(new Student(20,"李四"));
    stk.push(new Student(22,"王五"));
    stk.push(new Student(17,"赵六"));
    System.out.println("stk="+stk);
    //把Stack当作Vector看待
    stk.addElement(new Student(18,"黄七"));
    System.out.println("第三个学生是:"+stk.elementAt(2))
    System.out.println("移出栈的顺序是:");
    while (!stk.empty()) {
    System.out.println(stk.pop());
    }
    }
    }

    (5)HashMap(“键-值映射对”的方法,此处使用学生的年龄作为键)

    测试代码( HashMapDemo.java)如下所示:

    import java.util.HashMap;
    import java.util.*;
    public class HashMapDemo {
    /**  * @param args  */
    public static void main(String[] args) {
    HashMap<String,Student> hashmap=new HashMap();
    hashmap.put("18", new Student(18,"张三"));//存放对象用put方法
    hashmap.put("20", new Student(20,"王五"));
    hashmap.put("22", new Student(22,"李四"));
    System.out.println("HashMap:"+'
    '+hashmap);
        //该函数有其内部的排序方式,事实上是依据哈希算法来排序的。
    Set set=hashmap.keySet();//获取全部键,返回类型是Set
    
    Iterator iterator=set.iterator();
    while (iterator.hasNext()) {
    //System.out.println(iterator.next()+"="+hashmap.get(iterator.next())+";");
    System.out.println(hashmap.get(iterator.next())+";");
    }
    }
    }

    (6)TreeMap

        TreeMap容器类比较特殊,TreeMap内部使用红黑树结构对“键”进行排序存放,所以放入TreeMap中的“键-值”对的“键”必须是可排序的。

    测试代码(TreeMapTest.java)如下所示:

    import java.util.Iterator;
    import java.util.Set;
    import java.util.TreeMap;
    public class TreeMapTest {
    public static void main(String[] args) {
    TreeMap treemap=new TreeMap();
    treemap.put("18",new Student(18,"张三"));
    //指定键值,如果映射以前包含一个此键的映射关系,那么将替换原值
    treemap.put("21",new Student(21,"王五"));
    treemap.put("19",new Student(19,"赵六"));
    System.out.println("
    TreeMap:
    "+treemap);//可以对键排序
    System.out.println(treemap.firstKey());//返回第一个键
    Set set=treemap.keySet();
    Iterator iterator=set.iterator();
    while (iterator.hasNext()) {
    System.out.println(treemap.get(iterator.next())+";");
    } }}

    (7)Properties类(实现属性的读取和存放)

    Properties类表示了一个持久的属性集,它可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串,它继承自HashTable,也即哈希表。Properties类存放的“键-值”对都是字符串。

    测试代码(PropertiesTest.java)如下所示:

    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    import javax.security.auth.login.Configuration;
    
    public class PropertiesTest {
    /**  * @param args  */
    public static void main(String[] args) {
    //获取文件,并读入到输入流
    InputStream is=Thread.currentThread().getContextClassLoader()
    .getResourceAsStream("Config.properties");
    //创建属性级对象
    Properties prop=new Properties();
    try {
    //从流中加载数据
    prop.load(is);
    } catch (IOException e) {
    e.printStackTrace();
    }
    String name=prop.getProperty("name");
    System.out.println("name="+name);
    String idString=prop.getProperty("id");
    System.out.println("id="+idString); }
    }

    在此需要创建一个属性文件,命名为:config.properties,放于工程的src目录中。

    属性文件内容如下:

    #key=value

    name=shenxiaolinu6C88u6653u9E9F

    id=105032013

    4、请问java中有没有优先队列实现类,如果有,请编写程序,演示该类的使用。

    优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。PriorityQueue是从JDK1.5开始提供的新的数据结构接口。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列。

    程序代码如下所示:

    import java.util.Comparator;
    import java.util.PriorityQueue;
    import java.util.Queue;
    import java.util.function.Function;
    import java.util.function.ToDoubleFunction;
    import java.util.function.ToIntFunction;
    import java.util.function.ToLongFunction;
    public class PriorityQueueTest {
          public static class Student {     //
    /**  * @param args */
    private int age;
    private String name;
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public Student() {
    super();
    // TODO Auto-generated constructor stub
    }
    public Student(int age, String name) {
    super();
    this.age = age;
    this.name = name;
    }
    public String toString() {
    return "Student [age=" + age + ", name=" + name + "]";
    } }
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    Comparator<Student> OrderIsdn =  new Comparator<Student>(){  
    public int compare(Student s1, Student s2) {
    // TODO Auto-generated method stub
     int age1 = s1.getAge();  
                 int age2 = s2.getAge();
                    if(age2 > age1)  
                    {   return 1; }  
                    else if(age2 < age1)  
                    {   return -1;}  
                    else  
                    {   return 0; }  
    }
            };  
         PriorityQueue<Student> priorityQueue =  new PriorityQueue<Student>(11,OrderIsdn);  
            Student s1 = new Student(18,"张三");  
            Student s3 = new Student(19,"李四");  
            Student s2 = new Student(17,"王五");  
            priorityQueue.add(s1);  
            priorityQueue.add(s3);  
            priorityQueue.add(s2);  
            while (!priorityQueue.isEmpty()) {
    System.out.println(priorityQueue.poll());  
    }
        }
    }

    五、实验总结

    1.本次实验按时按量完成。

    2.当有多个catch语句,在安排catch语句的顺序时,首先应该捕获子类异常,然后再捕获父类异常。如果顺序弄反了,后面捕获异常的代码将无法被调用。如果异常是同级关系,则无所谓哪个置前,哪个置后。

    3.如果有需要使用return语句时,一个合理的做法是,既不在try内部使用return语句,也不在 finally内部使用 return语句,而应该在finally语句之后使用return 来表示函数的结束和返回。

    4.一般都需要throw和throws语句的组合使用,就是在捕获异常后,抛出一个明确的异常给调用者。需要注意的是:throw语句是编写在方法之中的,而throws语句是用在方法签名之后的。在同一个方法中使用throw和throws时要注意,throws抛出的类型的异常范围要比throw抛出的对象范围大才可以。

    5.Stack类继承自Vector,而Vector又有父类,这样Stack中出现了多余方法。若我们只希望Stack栈完成进栈和出栈功能就行,而不需要add等方法,则可通过LinkedList来完成,因为LinkedList链表结构可以快速地实现插入和删除操作。

    6.因为PriorityQueueTest是一个动态的内部类,创建这样的对象必须有实例与之对应,程序是在静态方法中直接调用动态内部类会报错误。这样的错误好比类中的静态方法不能直接调用动态方法。可以把该内部类Student声明为static,或者不要在静态方法中调用。

    7.此次实验主要是练习熟悉Java异常处理机制以及Java集合框架和泛型机制。通过编程代码的实践加深对这些知识的理解和巩固。

     

     

     

  • 相关阅读:
    break-continue
    函数定义
    函数类型
    为何要继承SpringBootServletInitializer,为何要实现configure这方法
    查询一个表中的两个字段值相同的数据
    数据库中查出来的时间多8小时&查询数据正常展示少8小时
    @JsonFormat与@DateTimeFormat注解的使用
    用js获取当前月份的天数
    js获取当前年,月,日,时,分,秒
    maven配置和安装
  • 原文地址:https://www.cnblogs.com/shenxiaolin/p/4927298.html
Copyright © 2020-2023  润新知