22-04-21 西安 枚举类enum,实例初始化加载过程,类的初始化过程,异常Exception

22-04-21 西安 枚举类enum,实例初始化加载过程,类的初始化过程,异常Exception,第1张

枚举是jdk5.0的特性
用于创建固定数量对象的简化方式,如月份,星期,管理员角色

public enum 枚举类类名{
     对象名(实参),对象名(实参);

}


public enum Gender {
    BOY(),GIRL();
}
public class EnumDemo {
    public static void main(String[] args) {
        Gender boy1 = Gender.BOY;//获取对象的格式:枚举类名.对象名
        Gender boy2 = Gender.BOY;
        System.out.println(boy1==boy2);//true
        Gender girl1 = Gender.GIRL;
        Gender girl2 = Gender.GIRL;
        System.out.println(girl1==girl2);//true

    }
}

枚举类的注意事项:
1.枚举类里外都不可以new对象,只能通过枚举固定的格式创建对象。new  Gender();//会报错
2.如果枚举类没有任何的构造器时,jvm会自动提供一个private的无参构造器,反之不提供
3.枚举类中的构造器权限访问级别只能是private,如果不写权限访问级别,jvm会自动补上private
4.枚举类中对象如果使用无参构造器创建对象,对象名后面的()可以全部省略不写。
5.枚举类中对象创建的代码必须在枚举类的第一行,否则编译报错

public enum Gender {
    BOY,GIRL;
}

6.枚举类中对象隐式被 public static final关键字修饰,自己手动显示会编译报错
7.程序中所有的枚举类都隐式extends Enum,再无法继承其他类,但是可以实现接口
8.在枚举类的构造器中无法显示使用super()      super is not allowed in enum constructor

Enum中只有一个构造方法
protected Enum(String name,int ordinal)
程序员无法调用此构造方法。该构造方法用于由响应枚举类型声明的编译器发出的代码

9.枚举类不能拥有子类。枚举类不能被其他类继承


只能说鬼斧神工

Gender boy = Gender.BOY;沙老师,为什么这行代码会调用俩次 Gender的无参构造器呀?

因为创建对象的代码在类的成员位置,所以当你用的时候,它随着类的加载就加载啦,但只加载一次,不会太浪费,有隐式的static呢。真是似懂非懂呢,结合下文类加载过程好像懂了

public enum Gender {
    BOY, GIRL;

    Gender() {
        System.out.println("Gender类无参构造器");
    }
}

class EnumDemo2 {
    public static void main(String[] args) {
        Gender boy = Gender.BOY;
    }
}


笔试题经常遇到的三个点
1. 包装类和String常量区问题
2.实例和类的初始化过程
堆内存每块区域中的变量都有默认值
类的初始化:
补充:静态变量的隐式初始化
实例初始化:
补充:实例变量的隐式初始化(赋默认值)
--------

 实例初始化加载过程:

原则:

1.显示或隐式的super(实参)或显示的this(实参)
2.实例成员(实例变量显示赋值 *** 作,实例常量,实例方法,实例内部类)和构造器代码块加载优先级一样,谁在前优先加载谁
3.再加载构造器中除了super(实参)或this(实参)的显示内容

1.无继承关系

public class Superclass {
        //实例变量
        int num=method();
        //实例方法
        private int method(){
            System.out.println("实例变量的显示赋值 *** 作");
            return 10;
        }

        public Superclass(){
            System.out.println("无参构造器第三部分代码");
        }

        {
            System.out.println("构造器代码块");
        }
}
class EnumDemo3 {
    public static void main(String[] args) {
        Superclass superclass = new Superclass();
    }
}}

2,有继承关系 

public class Superclass {
        //实例变量
        int num=method();
        //实例方法
        private int method(){
            System.out.println("父类实例变量的显示赋值 *** 作");
            return 10;
        }

        public Superclass(){
            System.out.println("父类无参构造器显示代码");
        }

        {
            System.out.println("父类构造器代码块");
        }
}

  class Subclass extends Superclass{
    //实例变量
    int num=method();
    //实例方法
    private int method(){
        System.out.println("子类实例变量的显示赋值 *** 作");
        return 10;
    }

    public Subclass(){
        System.out.println("子类无参构造器显示代码");
    }

    {
        System.out.println("子类构造器代码块");
    }
}

class EnumDemo3 {
    public static void main(String[] args) {
        Subclass subclass = new Subclass();
    }
}


this关键字第三种用法
在父类中使用this,this是父类类型的子类对象(多态)

场景:在父类的构造器中或者实例方法中
语法格式:
this.实例变量
this.实例方法(实参)

巨坑的题:

public class Superclass {
    //实例变量
    int num=10;
    //实例方法
    public void method(){
        System.out.println("num="+num);
        System.out.println("this"+this);
    }

    public Superclass(){
        this.method();//在父类中使用this,this是父类类型的子类对象(多态)
    }

}
class Subclass extends Superclass{
    //实例变量
    int num=20;
    //实例方法
    @Override
    public void method(){
        System.out.println("num="+num);
    }

    public Subclass(){
        super();
    }
}

 class EnumDemo {
    public static void main(String[] args) {
        Subclass subclass = new Subclass();//num=0
        //只创建了一个子类,子类才有地址值。父类并没有在堆开辟空间,父类中打印的this肯定不是父类的对象
    }
}


类的初始化过程:
随着字节码文件的加载而加载,且只加载唯一的一次

原则:

静态成员(静态变量,静态常量,静态方法,静态内部类)和静态代码块加载优先级一样,谁在前加载谁,而且只加载唯一的一次。

1.无继承关系

 class Superclass{
    static int num= method();
    //实例方法
    public static int method(){
        System.out.println("静态变量的显示赋值 *** 作");
        return 10;
    }
    static{
        System.out.println("静态代码块");
    }

}
class Demo{
    public static void main(String[] args) {
        new Superclass();
        new Superclass();
        new Superclass();
    }
}

2.有继承关系

public class Superclass {
    static int supernum = method();

    public static int method() {
        System.out.println("父类静态变量的显示赋值 *** 作");
        return 10;
    }

    static {
        System.out.println("父类静态代码块");
    }
}


class Subclass extends Superclass {
    static int subnum = method1();

    public static int method1() {
        System.out.println("子类静态变量的显示赋值 *** 作");
        return 10;
    }

    static {
        System.out.println("子类静态代码块");
    }
}

class Demo {
    public static void main(String[] args) {
        new Subclass();
        new Subclass();

    }
}


Throwable类

学习异常的好处:不能把服务器搞垮了,不能让jvm挂掉

Throwable :   XxxError或XxxExceptio的父类 ,所有错误或异常的超类
     1.XxxError是无法通过程序的后续代码进行解决,只能事先避免
     2.Exception:程序中出现的不正常情况,最终导致jvm正常停止,这种情况可以通过程序的后续代码进行补救

Throwable类中常用的方法:

  1. Throwable(String message)   构造带指定详细消息的新 throwable。
  2. printStackTrace()   //打印Throwable对象的详细信息,红色字体
  3. getMessage()   //  返回Throwable构造器中给的字符串。

Exception分类
Exception 类及其子类是 Throwable 的各种异常情况的分类。
Exception(String message)   构造带指定详细消息的新异常。

运行时异常:RuntimeException及其子类
     特点:代码没有任何语法格式错误,但在运行期间出现了数据上的问题。如空指针异常
 

编译时异常: Exception及其子类(RuntimeException及其子类除外)
     特点:代码没有任何语法格式错误,但在编译期间出现了编译错误。如:FileInputStream stream = new FileInputStream("w");

运行时异常jvm会干啥:
       jvm会调用异常对象的父类方法,打印堆栈信息。然后让程序立刻停止。【补充:jvm不仅帮你new异常,还要throw,抛给main方法。main方法没有进行异常处理就给调用者jvm。】


异常处理的4个关键字
throws,try,catch,finally,以及异常处理的前提关键字 throw

异常声明:(将异常信息在方法进行标记,交给调用者进行解决)
        throws
异常捕获:(将异常信息自己处理)
        try,catch,finally

抛出一个异常对象

        throw用在方法内,用来抛出一个异常对象,并结束当前方法的

1.在程序中,无论是运行时异常还是编译时异常都必须解决。
2.运行时异常解决套路:
     可以程序员手动解决,也可以程序员不解决,交给jvm进行解决。
     手动解决:throws,try...catch
     自动解决:jvm处理(调用异常对象的printStackTrace,终止jvm)
3.编译时异常必须由程序员手动解决。

throw关键字,抛出异常对象(让jvm识别到该异常对象)

throw new IOException("自定义IO异常对象");//会编译报错  
throw new RuntimeException("自定义运行时对象");//不会编译报错

4.异常声明:
在方法内部不进行解决,在方法声明上进行标记,交给调用者解决
        修饰符 返回类型 方法名()throws 异常类名1,异常类名2{

        }

        4.1当方法中存在多个异常时,进行异常声明的时候无需考虑异常声明顺序(就算有异常间继承关系也不需要考虑,不会编译报错)
        4.2当方法中存在多个异常时,进行异常声明的时候可以简化,只声明父类异常即可。


声明的异常类存在子父类继承关系

异常所在的类在父子类当中;
   1.如果异常在父类被重写的方法中,子类重写父类含有异常的方法时。无需考虑父类该方法的异     常情况
   
   2. 如果异常在子类重写的方法中,必须通过异常的捕获进行处理。不能用throws


public class Superclass {
    //实例变量
    int num=10;
    //实例方法
    public void method(){
        System.out.println("num="+num);
        System.out.println("this"+this);
    }

    public Superclass(){
        this.method();
    }
}


public class Subclass extends Superclass{
    //实例变量
    int num=20;
    //实例方法
    @Override
   //子类重写父类方法,有异常是必须try...catch,用声明异常会编译报错
    public void method() throws IOException{
        throw new IOException("自定义IO异常对象");
    }

    public Subclass(){
        super();
    }
}

异常的捕获:
出现不同的异常都有对应的解决方案。

try{
      //可能出现异常的代码
}catch( 异常类型 对象名){
    //出现该异常的解决方案[事务],从而保证程序继续运行
}catch(异常类型 对象名){
}

代码中的异常类存在子父类继承关系
1、如果子父类解决方案不同,没有依赖关系,分别捕获用多个try。多次捕获,多次处理,对应      method02(1,1)。
2、如果子父类解决方案不同,有依赖关系。一次捕获,多次处理,此时俩个异常不可能同时处理了。分别处理时,需要将异常子类的处理方案写在最上面。对应method01(1,1)。
3、如果子父类解决方案相同,可以一次捕获,一次处理。

public class ExceptionDemo {
    public static void main(String[] args) {
        method01(1, 1);
        method02(1, 1);
    }

    public static void method01(int a, int b) {
        try {
            if (a == 1) {
                throw new FileNotFoundException("自定义文件找不到异常");
            }
            if (b == 1) {
                throw new IOException("自定义IO异常");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void method02(int a, int b) {

        if (a == 1) {
            try {
                throw new FileNotFoundException("自定义文件找不到异常");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        if (b == 1) {
            try {
                throw new IOException("自定义IO异常");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

异常类所在的类存在子父类继承关系

  • 子类重写父类含有异常的方法时,无需考虑父类该方法的异常情况。
  • 如果异常在子类重写的方法中,必须通过异常的捕获进行处理。不能用throws

finally关键字

当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。

1.不使用finally去关闭资源,经测试好用。不管最后有没有报异常,最后都执行了关闭资源的 *** 作

public class ExceptionDemo {
    public static void main(String[] args) {
        method01();
    }

    public static void method01() {
        //局部变量不初始化不能用
        Scanner sc = null;
        try {
            sc = new Scanner(System.in);
            System.out.println("请输入一个整数");
            int anInt = sc.nextInt();
            System.out.println("anInt=" + anInt);
            System.out.println("关闭资源");
            sc.close();
        } catch (Exception e) {
            e.printStackTrace();
            if (sc != null) {
                System.out.println("关闭资源");
                sc.close();
            }
        }
    }
}

2.使用finally简简单单优化上面的代码

public class ExceptionDemo {
    public static void main(String[] args) {
        method01();
    }

    public static void method01() {
        Scanner sc = null;
        try {
            sc = new Scanner(System.in);
            System.out.println("请输入一个整数");
            int anInt = sc.nextInt();
            System.out.println("anInt=" + anInt);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sc != null) {
                System.out.println("关闭资源");
                sc.close();
            }
        }
    }
}

finally注意事项
1.在try里准备执行return时,突然jvm发现return是结束方法的意思,后续还有一个finally,会先执行finally,try里的return暂缓执行
2.在try,catch,finally里尽量避免使用return关键字。

又是一个被坑惨了的代码。。。

public class ExceptionDemo {
    public static void main(String[] args) {
        int num = method01();
        System.out.println("num="+num);//num=10
    }

    public static int method01() {
        int a = 10;
        int b = 20;
        try{
            System.out.println("try");
            return a;  //已经决定return 10了,a在finally里再改也没用。
        }catch(Exception e){
            e.printStackTrace();
            return 1;
        }finally{
            a=a+b;
        }
    }
}


 自定义异常:

1.自定义运行时异常:
        1.1自定义运行时异常类。让这个类继承RuntimeException
        1.2 根据实际需求生成合适的构造器,至少2个(无参,String参数)
2.自定义编译时异常:
        2.1自定义编译时异常类。让这个类继承Exception
        2.2 根据实际需求生成合适的构造器,至少2个(无参,String参数)

自定义一个运行时异常

public class ZDYrunTimeException extends RuntimeException{

    public ZDYrunTimeException() {
    }

    public ZDYrunTimeException(String message) {
        super(message);//这行代码很关键。。。
    }
}

测试类:

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            throw new ZDYrunTimeException("我和你");
        }catch (ZDYrunTimeException zdYrunTimeException){
            zdYrunTimeException.printStackTrace();
            System.out.println(zdYrunTimeException.getMessage());
        }
    }
}

运行结果:

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/720123.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存