反射,枚举,异常

反射

对任一类,能知道该类的所有属性和方法;对任一对象,能调用它的任意方法和属性

获取Class对象

要想对类进行反射,首先需要获取类的对象,有三种方法

每个类的Class对象数量只有一个

1.通过getClass获取对象

People p1 = new People();
Class c1 = p1.getClass();

2.类名.class

Class c2 = People.class;

3.通过Class对象的forName()静态方法
在使用该方法时可能抛出ClassNotFoundException异常

Class c3 = Class.forName("People");
反射方法

在诸多反射方法中存在三个最重要的类型
1.Filed[] 获取类的所有属性
getDeclaredFields中Declared的含义为私有属性的获取,如在方法中不加该修饰词,则只会获得类中的public属性

//获取获取类的所有属性
Field[] fileds = c1.getDeclaredFields();
for(Field field : fileds){
    System.out.println(field.getName());
}
//获取类中私有属性name
Field f1 = c1.getDeclaredField("name");

2.Method[] 获取类的所有方法

Method[] methonds = c2.getDeclaredMethods();
for(Method methond : methonds){
   System.out.println(methond.getName());
}

3.Constructor 获取类的构造方法
在获取到类的构造方法后,可以用setAccessible(true) 启用访问安全检查的开关,即如果该类的构造函数为private的,可以通过class对象给该类创建一个实例对象

//获取People类中无参数的构造方法
Constructor c2=c1.getDeclaredConstructor();
c2.setAccessible(true);
People p1=(People)c1.newInstance();
System.out.println("无参数的私有构造函数\t"+p1);
//获取People类中有参数的私有构造方法,并给定一个参数 “Allen”
Constructor c3 = c1.getDeclaredConstructor(String.class);
c3.setAccessible(true);
People p2=(People)c3.newInstance("Allen");
System.out.println("有参数的构造函数\t"+p2.getName());

枚举

如下所示即为一个简单的枚举类,枚举类中的每个数据成员都是一个对象,例如Color类中的RED,GREEN

public enum Color{
    RED,GREEN,BLUE,BLACK;
}

枚举类不可以产生实例对象,因为自定义的枚举,都是继承

枚举类是一个抽象类,在枚举类中构造函数都是默认私有的,但是枚举类的私有构造方法是不能通过反射机制去调用的 因为在源代码中的Constructor类的
newInstance方法中存在下述语句:

if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");

这表明如果用newInstance方法去反射枚举类中的私有构造函数,会抛出IllegalArgumentException异常

枚举类中的方法
enum Color{
    RED,GREEN,BLUE,BLACK;
  • 返回当前实例,及其序号
public class TestDemo1 {
    public static void main(String[] args) {
        Color color = Color.BLACK;
        Color color1 = Color.BLUE;
        //序号
        System.out.println(color.ordinal());//3
        //返回当前实例
        System.out.println(color.name());//BLACK
        System.out.println(color.toString());//BLACK
        System.out.println(Color.valueOf("BLACK"));//BLACK
    }
}
       
  • 枚举实例的比较
public class TestDemo1 {
    public static void main(String[] args) {
        Color color = Color.BLACK;
        Color color1 = Color.BLUE;
        Color color2 = Color.BLACK;
        //比较
        System.out.println(color.equals(color1));//false
        System.out.println(color.equals(color2));//true
        System.out.println(color == color1);//false
        System.out.println(color == color2);//true
    }
}
  • 比较序号差值
public class TestDemo1 {
    public static void main(String[] args) {
        Color color = Color.BLACK;
        Color color1 = Color.BLUE;
        Color color2 = Color.BLACK;
        //color.compareTo(color1)  color序号-color1序号
        System.out.println(color.compareTo(color1));// 1
        System.out.println(color.compareTo(color2));// 0
    }   
}
  • values方法
    values把枚举的实例,都变成一个数组
public class TestDemo1 {
    public static void main(String[] args) {       
        //values把枚举的实例,都变成一个数组,这个方法是由编译器自己生成的
        //静态方法
        for (Color c : Color.values()
                ) {
            System.out.println(c);
        }
    }   
}

输出结果在这里插入图片描述

在枚举类中创建有参数的构造函数
public enum Color {
    RED(1), GREEN(2), BLUE(3), BLACK(4);
    private final int id;
    
    Color(int id) {
        this.id = id;
    }
}

异常

在这里插入图片描述
java中的异常主要包括两个子类,:Exception(异常)和 Error(错误)

Error(错误)

Error是程序无法处理的错误,表示运行应用程序中较严重问题,表示代码运行时 JVM(Java 虚拟机)出现的问题。
StackOverFlowError表示栈溢出异常
OutOfMemoryError 表示堆溢出异常

Exception(异常)

Exception 类有一个重要的子类 RuntimeException,RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。

抛出异常

例子:

运行期间的异常:
public class TestDemo3 {
    public static void main(String[] args) {
        int a = 10;
        int d = a/0;
        System.out.println(d);
    }
}

输出结果:
在这里插入图片描述

编译期间的异常
public class TestDemo3 {
//在需要抛出异常的方法后添加 throws 异常类型
    public static void main(String[] args) throws ClassNotFoundException {
            //.forName("People") 需要抛出ClassNotFoundException异常
            Class c1 = Class.forName("People");
    }
}

try ……catch捕获异常并打印

运行顺序为先运行try中的语句,如果遇到异常,则从异常位置开始跳至catch语句中执行,try中异常位置之后的语句不再执行

public class TestDemo3 {
    public static void main(String[] args) {
        try {
            int[] array = {1, 2, 3, 4};
            System.out.println(array[4]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("有异常");
            e.printStackTrace(System.out);
        }
    }
}

输出结果:
在这里插入图片描述

try ……catch之后的finally

finally中的语句在try和catch中语句执行之后才会执行,如果try,catch和finally中存在返回值,finally中的返回值会覆盖 try 或者 catch 中的返回值。
如:

public class TestDemo3 {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test() {
        try {
            int a = 10;
            int b = a/0;
            System.out.println(b);
            return 1;
        }catch (Exception e) {
            System.out.println("有异常");
            e.printStackTrace(System.out);
            return 2;
        }finally {
            return 3;
        }
    }
}

在上面的程序中,无论是去掉try中的return 1,或者去掉catch中的return 2,最终的返回值都会是3,如下图所示
在这里插入图片描述

finally使用的注意事项

  • 不要在fianlly中使用return。
  • 不要在finally中抛出异常。
  • finally中不要做一些其它的事情,仅仅用来释放资源是最合适的。
  • 尽量将所有的return写在函数的最后面,而不是try … catch … finally中。
final finally finalize 的区别

1.final 修饰变量成为常量;final 修饰类,表示密封类,不能再被继承;final 修饰方法,表示该方法在子类中不能 被重写
2.finally 用于异常处理,finally 中的代码无论如何都会执行,一般用于释放资源
3.finalize 用于对象的回收,在 GC 回收某个对象的时候,对象的 finalize 方法会被先执行一遍

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值