java基础第四篇

自定义异常类

系统提供的异常类不足

需求:模拟feiq上线如果没插网线,就抛出一个没插网线的异常,如果,插上网线,正在显示好友列表。

利用ip来判断一下有没有网线这里模拟成字符串。

自定义一个类来继承Exception类:

自做:完成这个ip异常处理

利用父类的Exception来处理异常对象

我们还可以不捕获,继续抛出去,比如main调用,我们就抛给虚拟机

1.演示一个自定义异常,完了把它抛给虚拟机

class Excep

{

public static void main(String[] args) throws NoIpException

{  

String ip=null;

/*try{

feiQ(ip);

}catch(NoIpException e)

{

e.printStackTrace();//打印异常栈信息

}*/

feiQ(ip);

}

public static void feiQ(String ip)

{

if(ip==null)

{

throw new NoIpException("没有插网线");

}

System.out.print("正常显示");

}

}

//继承一下老大

class NoIpException extends Exception

{

public NoIpException(String str)

{

super(str);//传递错误信息

}

需求:吃法,10元,没带够钱的异常,如果带够了,就可以吃饭了。

自己来做这样一个异常。

//定义一个没带钱的异常
//把这个异常用在一个方法上
class NoMoneyException extends Exception{
    //传入异常信息
    public NoMoneyException(String message){
        super(message);
    }
}

public static void eat(int money) throws NoMoneyException{
        if(money < 10){
            //函数内部抛出一个异常,函数声明上面我得抛啊
            throw new NoMoneyException("我钱不够,我特么吃不了饭");
        }else{
            System.out.println("我现在可以吃饭了");
        }
    }

下面来说一下:如果方法内部抛出一个运行时异常,运行时异常在方法上可声明就声明,想处理就处理

Exception:1.运行时异常(通过程序员良好的习惯去避免)2.编译时异常

什么是运行时异常?

除了上面运行时异常,就是编译时异常。

那么多,怎么记?

不用记。

直接用文档查就好了。

               

上面就是抛出了一个线程中断异常,为什么必须抛出一个线程中断异常呢?而这个异常又是一个编译异常

我们看看wait()本身这个函数

很明显它是抛出了一个线程中断时异常。

我们知道调用一个抛出了异常的方法,我们必须进行处理,要么捕获,要么进行抛出,特别又是编译异常的函数。

下面我们来说另外一个问题:

一个读取,一个删除,能不能成功。明显不能。

说明资源文件一旦使用完毕,一定要释放,不然其他程序将无法操作此文件。这种事情是程序来做的。

就算是读到一半出了异常,也要把文件释放出去,别人才可以来对文件进行操作

finally 块;

finally块的 使用前提是必须要存在try块才能使用。

finally块的代码在任何情况下都会执行的,除了jvm退出的情况。

finally非常适合做资源释放的工作,这样子可以保证资源文件在任何情况下都 会被释放。

第一种: 比较适用于有异常要处理,但是没有资源要释放的。

 try{

可能发生异常的代码;

}catch(捕获的异常类型 变量名){

处理异常的代码;

}

第二种:比较适用于既有异常要处理又要释放资源的代码。

try{

可能发生异常的代码;

}catch(捕获的异常类型 变量名){

处理异常的代码;

}finally{

释放资源的代码;

}

第三种: 比较适用于内部抛出的是运行时异常,并且有资源要被释放。

   try{

可能发生异常的代码;

}finally{

释放资源的代码;

}

上面就退出了虚拟机,不会执行那个finally块中的代码

下面我们简单来写一个读取文件异常的代码处理:

简单说一下泛型

1。接口泛型

            接口泛型是在实现接口的时候指定的类型
            当然在实现接口的时候也可以不传递具体的类型,他默认就为Object类型
            很可能就是你在用的时候,要手动变为相应的数据类型

2.泛型的上下限
   

public class UpperBoundedExample {
    public static <T extends Number> double sum(List<T> list) {
        double sum = 0;
        for (T element : list) {
            sum += element.doubleValue();
        }
        return sum;
    }

    public static void main(String[] args) {
        List<Integer> integers = Arrays.asList(1, 2, 3);
        List<Double> doubles = Arrays.asList(1.5, 2.5, 3.5);

        System.out.println("Sum of integers: " + sum(integers));
        System.out.println("Sum of doubles: " + sum(doubles));
    }
}

 在这个例子中,<T extends Number> 表示泛型 T 必须是 Number 类或其子类。这使得 sum 方法可以接受 List<Integer>List<Double>

public class LowerBoundedExample {
    public static void addNumbers(List<? super Integer> list) {
        for (int i = 1; i <= 5; i++) {
            list.add(i);
        }
    }

    public static void main(String[] args) {
        List<Object> objectList = new ArrayList<>();
        addNumbers(objectList);

        System.out.println("Numbers added to the list: " + objectList);
    }
}

 在这个例子中,<? super Integer> 表示泛型的类型必须是 Integer 或者 Integer 的父类型。这使得 addNumbers 方法可以接受 List<Object> 或更泛化的类型。

泛型的几个引用规则

1.如果一个接口定义了泛型,普通类(没有泛型接口的类)去实现它的时候必须指明确定的类型
2.但是如果这个类也标明了相应的泛型,就可以不指定类型,后面new的时候在标出具体的类型就可以
    class Test2Demo1<K,V> implements Test2.Entry<K,V> {
3.不管是静态方法还是非静态方法,都是按照下面这种格式定义泛型
    //在泛型参数上指定上限
    public <T extends SomeType> void myMethod(T value) {
    // 方法体
    }
    //在方法参数上指定上限
    public <T> void myMethod(List<? extends SomeType> myList) {
    // 方法体
    }
4.泛型中传入指定类型,这个指定类型也可以包含泛型
     public static <K extends Comparable<K>,V> Comparator<Entry<K,V>> comparingByKey()
     public interface Comparator<T>我们来看这个Comparator比较器本身就要传入一个泛型
     然后我们上面传入的是一个Entry接口实现类,这个实现类又包含了<K,V>泛型
5.在泛型方法中,可以独立于类上声明的新泛型参数
    public class Example<T> {
    private T value;

       // 类级别的泛型参数 T
    public Example(T value) {
        this.value = value;
    }

    // 泛型方法,定义了独立于类级别的泛型参数 U
    public <U> void printU(U u) {
        System.out.println(u);
    }

6.在Java的泛型中,通配符的上下限是有限制的。可以使用 extends 关键字指定上限,但不建议使用 super 关键字指定下限。这是因为泛型的下限通配符(super)并不适用于接口。因为接口本身不能继承类,只能继承其他接口
说一下继承关系与实现关系是不同的概念,但是他们都可以被认为是一种类型的关系。
当使用泛型的时候,它的上限与下限都必须落实当可以有具体的类
对于一个接口来说,如果用<? super 接口> ,那么就是说泛型必须是接口的父类,也就是接口去extends另外接口
而另外的接口不是一个具体的类                                                                                                        7. 关于方法返回值强制转换&拼接多个接口的问题                                                                                   除非这个接口是一个声明式接口,没有任何的实现方法

对上面的返回来说Serializable是被Comparator显示声明实现的 ,并且没有没有任何抽象方法声明

另外说一点,在java中,如果一个接口有默认方法,它的实现类是可以去调用这个方法的。                            8.            

你说这里为什么也是传入<? super T>传入T或者T的父类呢

假设一个类Entry就是定义了很多的方法比如得到getKey (),getValue(),然后内部还定义了很多的比较器的方法,调用一个方法会返回一个比较器

一个带有K与V的类,比如下面这个类,或者其他的类,全部实现这样一个方法

 然后泛型T可能传入的就是一个Node类型,那么比较器可能就是下面的类型

这里的Entry就是它的父类型

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值