JAVA学习4-枚举、异常、List

31.枚举

枚举编译之后也是生成class文件;

枚举也是一种引用数据类型;

枚举中的每一个值可以看作是常量;

结果超过两种,并且可以一枚一枚列举出来的可以使用枚举类型,例如颜色、四季、星期等;

public static void main(String[] args) throws Exception {
        Res r = App.divide(3, 5);
        if (r == Res.SUCCESS) {
            System.out.println("成功");
        }
        Res r2 = App.divide(3, 0);
        if (r2 == Res.FAIL) {
            System.out.println("失败");
        }
}

public static Res divide(int a, int b) {
        try {
            int c = a / b;
            return Res.SUCCESS;
        } catch (Exception e) {
            // TODO: handle exception
            return Res.FAIL;
        }
}

enum Res {
        SUCCESS, FAIL
}

32.异常

异常:程序运行过程中的不正常情况;

异常作用:增强程序的健壮性;

异常在java中以类的形式存在,每个异常类都可以创建异常对象;

异常Exception分为两大类:运行时异常(未受检异常/非受控异常)与编译时异常(受检异常/受控异常);

编译时异常表示必须在编写程序的时候预先对这种异常进行处理,否则编译报错;

运行时异常在编写程序时可以选择处理与不处理;

所有异常都是在运行时发生的,编译阶段是不会发生的,因为只有运行阶段才能new异常对象,异常的发生就是new异常对象;

编译时异常发生的概率比较高,对于发生概率比较高的异常需要在运行前进行预处理;运行时异常发生的概率比较低,没有必要对发生概率比较低的异常在运行前预处理;

异常的处理:

java中对异常的处理有2中方式:

①在方法声明的位置上使用throws关键字,抛给上一级(调用者);

②使用try...catch语句进行方法的捕捉;

如果异常一直上抛,直到main方法,main方法未处理,则抛给jvm,jvm则终止程序执行;

编译时异常:

//必须在编写代码时处理该异常,否则程序报错
public static void main(String[] args) {

        App.test();
}

public static void test() throws ClassNotFoundException {
        System.out.println("aaaa");
}

异常处理机制的作用就是增加程序的健壮性,即使发生了异常也不会影响程序的执行;所以一般建议在main方法中使用try...catch捕获异常;

33.try...catch

程序new异常对象,抛出异常后,进行try...catch捕捉的话,最终会把异常对象的内存地址赋值给e;

try语句块中的代码有异常的话程序不会执行try语句块的代码,而是执行catch语句块中的代码,后溪代码继续执行;

catch后面的括号可以是具体类型也可以是具体类型的父类型;

catch可以写多个,建议写精确的异常类型捕获,可以利于代码快速查找bug;

catch写多个的时候,从上到下依次不能是从父类到子类;

public static void m3() {
        System.out.println("m3");
        try {
            FileInputStream f = new FileInputStream("D://a.txt");
            System.out.println(100 / 0);
            f.read();

        } catch (FileNotFoundException | NullPointerException | ArithmeticException e) {
            // TODO Auto-generated catch block
            System.out.println("文件不存在");
            // e.printStackTrace();
        } catch (IOException e) {
            System.out.println("文件无法读取");
        }
        
        System.out.println("m3-2");
}

如果希望调用者处理异常则用throws,否则都用try...catch处理异常;

 异常对象的两个重要方法:

获取异常的简单描述信息:

NullPointerException n = new NullPointerException("空指针");
System.out.println(n.getMessage());

 打印异常追踪的堆栈信息:

public static void main(String[] args) {
        try {
            m1();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("m000");
}

实际开发中建议使用e.printStackTrace(),更加便于观察代码错误;

异常追踪信息从上往下看,跳过SUN公司代码,即可发现bug代码所在位置;

异常只有抛出throw了,才会被系统当做异常对象处理,否则只是一个普通类;

捕获异常可以让程序不会因为一个异常而停止运行,导致发生程序停止运行,影响用户体验;

重写父类的方法不能比重写之前的方法抛出更多(更宽泛)的异常,可以更少;

34.try...catch的finally子句

在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常;

finally必须与try...catch同时出现,不能单独编写;

public static void m3() {
        System.out.println("m3");
        FileInputStream f = null;
        try {
            f = new FileInputStream("D://a.txt");
            System.out.println(f.toString());

        } catch (FileNotFoundException e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            // finally中的代码一定会执行
            // 流会占用资源,所以要关闭,在finally中执行是比较合适的
            if(f!=null){
                try {
                    f.close();
                } catch (IOException e) {
                    //TODO: handle exception
                }
            }
        }
}

 try可以与finally一起使用

try {
            System.out.println("try");
            return;
        } finally {
            System.out.println("fffff");
}

 finally的代码一定会执行,除非退出java虚拟机jvm

try {
            System.out.println("try");
            System.exit(0);
        } finally {
            System.out.println("fffff");
}

//java方法体中的代码必须遵循一条基本原则,即代码是自上而下依次执行;
public static void main(String[] args) {

        int i = m1();
        System.out.println(i);    //100
    }

    public static int m1() {
        int i = 100;
        try {
            return i;
        } finally {
            i++;
        }
}

35.Error错误

错误是不能处理的,所有的错误只要一发生就会终止程序的执行,退出jvm;

36.自定义异常

package exec;

public class MyException extends RuntimeException {

    public MyException() {

    }

    public MyException(String s) {
        super(s);
    }
}

public class App {
    public static void main(String[] args) {

        try {
            m1();
        } catch (MyException e) {
            // TODO: handle exception
            System.out.println(e.getMessage());
        }

    }
}

37.集合

集合实际上就是一个容器,一个载体,可以用来容纳其他类型的数据,可以容纳多个对象;

假如从数据库查出10条数据,java会将10条数据封装成10个对象,放入一个集合当中;

集合不能存储基本数据类型,不能存储java对象,集合中存储的都是java对象的内存地址(引用);

集合本身也是一个对象,也对应一个内存地址;

java中每一个不同的集合,对应不同的数据结构,往不同的集合中存储数据,就相当于把数据放到了不同的数据结构当中,不同的数据结构,数据的存储的方式不同,数据结构有:数组、二叉树、链表、哈希表;

使用不同的集合等同于使用不同的数据结构;

所有的集合类跟接口都在java.util包下;

java中集合分为两大类,一类是单个方式存储元素,一类是以键值对方式存储元素;

单个方式存储元素:这一类中超级父接口是java.util.Collection;

键值对方式存储元素:这一类中超级父接口是java.util.Map;

 

所有实现类:

ArrayList :底层是数组;

LinkedList :底层是双向链表;

Vector :底层是数组,线程安全,效率较低,使用较少;

HashSet :底层是HashMap,放到HashSet集合的中的元素,等同于放到了HashMap集合的key部分;

TreeSet : 底层是TreeMap,放到TreeSet中的元素相当于放到了TreeMap集合的key部分了;

HashMap :底层是Hash表;

HashTable :底层也是hash表,只不过线程安全,效率较低,使用较少;

Properties :线程安全的,key和value只能存储字符串String;

TreeMap :底层是二叉树,TreeMap的key可以自动按照大小顺序排序;

List集合存储元素的特点:

        有序:存进去和取出的顺序相同,每个元素都有下标;

        可重复:存进去的元素可以是相同的;

Set(Map)集合存储元素的特点:

        无序:存进去与取出来的顺序不一定相同,set集合的元素没有下标;

        不可重复:不能存储相同的元素;

SortedSet(SortedMap)集合存储特点:

        无序不可重复,但是SortedSet里面的元素是可以排序(按照大小顺序排列)的;

Map集合的key就是一个Set集合;往Set集合中存放数据,就是放到了Map集合的Key部分;

38.Collection

没有使用泛型的情况下,Collection中可以存储所有Object子类型元素,使用泛型后,collection中只能存储某种具体类型;

集合中不能直接存储基本数据类型,也不能存对象,只能存对象的引用地址;

Collection c = new ArrayList<>();
c.add(500);    //自动装箱
c.add(true);
c.add(new Random());
System.out.println(c.size());
c.clear();
System.out.println(c.contains("八佰2"));
c.remove("八佰");
Object[] objs = c.toArray();

Collection的contains方法底层是调用equals方法,所以存放在集合中的类型一定要重写equals方法,remove方法同理;

while(it.hasNext()){
    //next方法返回值类型必须是Object
    Object o=it.next();
}
Collection c = new ArrayList();
//此时获取的迭代器,指向的是集合中没有元素状态下的迭代器;
//集合结构一旦发生改变,迭代器必须重新获取;
Iterator it = c.iterator();
String a1 = "abc";
String a2 = "abc";
c.add(a1);
c.add(a2);

获取迭代器,相当于对当前集合拍了一张快照,然后迭代器参照这个快照进行迭代;

c.remove()方法只删除集合的元素,导致迭代器的快照和原集合不同,it.remove()删除集合的元素,同时删除快照的元素;

39.List

List特点:有序可重复;


List c = new ArrayList();

String a1 = "海王";
String a2 = "敦刻尔克";
String a3 = "阿凡达";
c.add(a1);
c.add(a2);
c.add(a3);
// 在指定位置添加元素,后面元素往后移动一位;
// 使用不多,因为对于ArrayList来说效率较低
c.add(1, "无间道");
//修改某个下标的元素
c.set(0, "蜘蛛侠");

Iterator it = c.iterator();
for (int i = 0; i < c.size(); i++) {
    //List的get方法遍历
    System.out.println(c.get(i));
}
//第一次出现的索引
System.out.println(c.indexOf("海王"));
//元素最后一次出现的索引
System.out.println(c.lastIndexOf("阿凡达"));
//删掉指定下标的元素
c.remove(0);

40.ArrayList

容量是虚拟的预留内存空间;

//默认数组容量是10(底层先创建一个容量为0的数组,当添加元素的时候,初始化容量为10)
ArrayList c = new ArrayList();

ArrayList c2 = new ArrayList<>(20);
// size方法是获取集合中元素的个数,不是容量
System.out.println(c2.size()); // 0

Collection c = new HashSet();
c.add(1);
c.add(2);
c.add(3);

ArrayList c2 = new ArrayList(c);


Iterator it = c.iterator();
for (int i = 0; i < c2.size(); i++) {
     System.out.println(c2.get(i));
}

ArrayList的扩容是原容量的1.5倍;

ArrayList底层是数组,建议尽可能少的扩容,因为数组扩容效率比较低,建议在使用ArrayList集合的时候预估一个较为准确的初始化容量;

数组的优点:检索效率高;缺点:随机增删效率较低,向末位增删效率不受影响,无法存储大容量数据,因为很难找到一段连续的大内存空间;

ArrayList不是线程安全的集合;

//非线程安全转线程安全
List l = new ArrayList<>();
Collections.synchronizedList(l);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

y_w_x_k

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值