枚举是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类中常用的方法:
- Throwable(String message) 构造带指定详细消息的新 throwable。
- printStackTrace() //打印Throwable对象的详细信息,红色字体
- 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());
}
}
}
运行结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)