反射,枚举,异常

一 .反射
反射的一个重要条件就是首先要获取class对象,而获取class的方式有以下几点:
(1)通过getclass对象来获取class对象;
(2)通过类名.class来获得;
(3)通过class.forName()来获取class对象;
例如:

class Student{
    public int age;
    private String name;
    public Student(){
    }
    private Student(String name) {
        this.name = name;
    }
    public void fun1() {
        System.out.println("fun1()");
    }

    private void fun2() {
        System.out.println("fun2()");
    }

    public String getName() {
        return this.name;
    }
}
public class TestDemo {
    public static void main(String[] args) throws ClassNotFoundException {
Student s1 = new Student();
Class c1 = s1.getClass();//通过 getClass 对象来获取Class对象
System.out.println(c1);
Class c2 = Student.class;//通过  类名.Class 来获取
System.out.println(c2);
Class c3 =Class.forName("Student");//通过 forname 的静态方法来获取 任何一个类都有一个隐含的静态成员变量 class
System.out.println(c3);
}
}

面试题:
(1)一个class里面有几个class对象?
答:一个class类里有一个对应的class对象,通过加载 ,链接,编译后生成.class文件,就产生一个class对象,用来表示这个类的信息。
(2)反射里三个重要的类型?
答: 1.Field(类的属性) Metho(类的方法) Constructor(类的构造函数)
下面是反射的一些典型的方法:
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes):
获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
getDeclaredConstructor():这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

class Student{
    public int age;
    private String name;
    public Student(){
    }
    private Student(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void fun() {
        System.out.println("fun1()");
    }

    private void fun2() {
        System.out.println("fun2()");
    }

    public String getName() {
        return this.name;
    }
}
public class TestDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Student s1 = new Student();
    Class c2 = Student.class;//通过  类名.Class 来获取
   System.out.println(c2);
Field[] fileds = c2.getDeclaredFields();//获取类的所有属性  包括私有属性
for (Field field : fileds) {
    System.out.println(field.getName());
    Method[] methonds = c2.getDeclaredMethods();//获得类的所有方法
for (Method methond : methonds) {
    System.out.println(methond.getName());
    Field f1 = c2.getField("age");//获取指定的属性public
System.out.println(f1);
  Field f2 = c2.getDeclaredField("name");//抛出异常 //获取private私有属性
f2.setAccessible(true); //启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
 System.out.println(f2);
 Student p3 = (Student) (c2.newInstance());//newInstancefang方法
f2.set(p3, "gff");
System.out.println(f2.get(p3));
//通过类的不带参数的构造函数创建这个类的对象;
Class c3 = Student.class;
Constructor c1 = c3.getDeclaredConstructor();
c1.setAccessible(true);
Student p1 = (Student) c1.newInstance();
System.out.println("无参数的私有构造函数\t" + p1);
Constructor c1 = c2.getDeclaredConstructor(String.class);
c1.setAccessible(true);
Student p1 = (Student) c1.newInstance("gff");
System.out.println("有参数的构造函数\t" + p1.getName());
      }
   }
}

二 .枚举
枚举是个抽象类,它不可以产生实例对象,原因是:自定义继承了Enum,构造函数默认为私有,枚举还可以作为switc的参数。
(1),枚举的构造函数时私有的
(2),每一个枚举成员都代表的是一个自身对象
(3)枚举一样可以定义方法,重载构造函数,定义抽象方法,然后让每一个成员去实现这个抽象方法,与普通类一样。

enum  Animals{
    DOG,PIG,CAT,BIRD//都是实例
}
public class Demo2 {    //枚举可以作为switch的参数
    public static void main(String[] args) {
        Animals animals = Animals.BIRD;
        switch (animals){
            case CAT:
                System.out.println("cat");
                break;
            case DOG:
                System.out.println("dog");
                break;
            case PIG:
                System.out.println("pig");
                break;
            case BIRD:
                System.out.println("bird");
                break;
                default:
                    System.out.println("==============");
        }
    }
}

枚举中的一些方法:
name()返回此枚举常量的名称,在其枚举声明中对其进行声明
ordinal()返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)
toString(),返回枚举常量的名称,它包含在声明中,name()方法与toString()几乎是等同的,都是输出变量的字符串形式。
compareTo(E o) ,比较此枚举与指定对象的顺序
getDeclaringClass(),返回与此枚举常量的枚举类型相对应的 Class 对象
equals(Object other) 当指定对象等于此枚举常量时,返回 true。
valueOf(Class enumType, String name)返回带指定名称的指定枚举类型的枚举常量。
values()把枚举的实例 都变成一个数组这个方法是由编译器生成的静态方法

enum Animals {
    DOG, PIG, CAT, BIRD//都是实例
}

public class Demo2 {    //枚举可以作为switch的参数
    public static void main(String[] args) {
        Animals animals = Animals.BIRD;
        Animals animals1 = Animals.CAT;
        System.out.println(animals.ordinal());//枚举常量的序数
        System.out.println(animals.toString());//枚举常量的名称
        System.out.println(animals.valueOf("CAT"));//指定名称的指定枚举类型的枚举常量。
        System.out.println(animals.name());//枚举常量的名称
        System.out.println(animals.compareTo(animals1));//比较此枚举与指定对象的顺序
        System.out.println(animals.getDeclaringClass());//返回与此枚举常量的枚举类型相对应的 Class 对象
        System.out.println(animals.equals(animals1));//当指定对象等于此枚举常量时,返回 true,否则为false。
       /* for (Animals a:Animals.values()
             ) {
            System.out.println(a);*/  //values把枚举的实例 都变成一个数组这个方法是由编译器生成的静态方法
        Animals[] animals2 = Animals.values();
        for (int i = 0; i < animals2.length; i++) {
        }
        System.out.println(Arrays.toString(animals2));
    }
}
public enum TestEnum1 {
    DOG("dog",1), PIG("pig",2), CAT("cat",3), BIRD("bird",4);//都是实例

    private final String name;
    private final int key;
    private TestEnum1(String name,int key){
        this.name = name;
        this.key = key;
    }
    public static TestEnum1 getkey(int key){
        for (TestEnum1 animals:TestEnum1.values()
                ) {
            if (animals.key == key){
                return animals;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        getkey(4);
        System.out.println(getkey(4).toString());
    }
}

在枚举类中构造函数都是默认私有的,但是枚举类的私有构造方法是不能通过反射机制去调用的
枚举中不能newInstance()
if ((clazz.getModifiers() & Modifier.ENUM) != 0)//如果给定的对象是枚举类型的就会抛出下面的这个异常
throw new IllegalArgumentException(“Cannot reflectively create enum objects”);

public enum TestEnum1 {
    DOG, PIG, CAT,BIRD;
    private TestEnum1(){//不带参数的构造函数

    }
  /*  DOG("dog",1), PIG("pig",2), CAT("cat",3), BIRD("bird",4);//都是实例
    private final String name;
    private final int key;
    private TestEnum1(String name,int key) {//带参数的构造函数
        this.key = key;
        this.name = name;
    }*/
  /* public void getInstance(){
        TestEnum1 testEnum1 = new TestEnum1();
   }*/

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
       Class animalEnum1 = TestEnum1.class;
       Constructor constructor = animalEnum1.getDeclaredConstructor(String.class,int.class);
         constructor.setAccessible(true);
        TestEnum1 p = (TestEnum1)constructor.newInstance();
        System.out.println("无参数的构造函数\t" + p);
    
        /*onstructor constructor = animalEnum1.getDeclaredConstructor(String.class,int.class,String.class,int.class);
        constructor.setAccessible(true);
        TestEnum1 p = (TestEnum1)constructor.newInstance("pig","猪");
        System.out.println("有参数的构造函数\t"+p);*/
    }
}

在这里插入图片描述
三 .异常
throwable是基类,他派生出错误(Error)和(Exception)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。
最典型的两个1.OutOfMemoryError 堆溢出
2.StackOverFlowError 栈溢出
Exception(异常):是程序本身可以处理的异常
异常又分为运行时期的异常和编译时期的异常,
有异常我们就要捕获异常:try -catch
有时我们也会用到:try - catch - finally
常见的异常:
1.数组越界:

public class lx2 {
    public static void main(String[] args) {
        int a[] = {1,2,3,4};
        try {
            System.out.println(a[4]);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("数组越界");
            e.printStackTrace();
        }
    }
}

算术运算:

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

        try {
            int a = 10;
            int b = a/0;
            System.out.println(b);
        }catch (ArithmeticException e){
            System.out.println("算术运算异常");
            e.printStackTrace();
        }
    }
}

在这里插入图片描述手动抛出异常:

   public static void main(String[] args) {
        String str = null;
        if (str == null) {
throw new NullPointerException("str == null");
        }
    }
}

在这里插入图片描述
捕获多个异常:

  public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try{
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            int result =devide(a,b);
            System.out.println("result:"+ result);
        }catch (ArithmeticException e){//算术运算异常
            System.out.println("ArithmeticException异常");
            e.printStackTrace();
        }catch (InputMismatchException e){//输入异常
            System.out.println("InputMismatchException异常");
            e.printStackTrace();
        }finally {
            scanner.close();
        }
    }
    public static int devide (int a, int b ){
        return a / b ;
    }
}

在这里插入图片描述

在这里插入图片描述
自定义异常类进行捕获

class SimpieException extends Exception{
    public SimpieException(String gff){
        super(gff);//带有参数的
    }
}
public class Test {
    public static void fun() throws SimpieException {
        throw new SimpieException("gff");
    }

    public static void main(String[] args) {
        Test test = new Test();
        try {
            test.fun();
        } catch (SimpieException e) {
            System.out.println("SimpieException 异常");
            e.printStackTrace();
        }
    }
}

finall解析:
在try - catch - finall里面的执行顺序:

public class Test {
    public static int Num(){
        int a = 3;
        try {
            System.out.println("1");
            a = 3/0;
            return 0;
        } catch (Exception e){
            System.out.println("2");
            return 1;
        }finally {
            System.out.println("3");
        }
    }
    public static void main(String[] args) {
        System.out.println("return value of Num:"+ Num());
    }
}

在这里插入图片描述
说明了 finally 语句块在 catch 语句块中的 return 语句之前执行。

finally 中的 return 会覆盖 try 或者 catch 中的返回值

public class Test {
    public static int Num(){
        try{
            return 1;
        }finally {
            return 2;
        }
    }
    public static void main(String[] args) {
        int result = Num();
        System.out.println(Num());
    }
}

Num开始执行进入try中,返回异常执行return1,finally做后执行时,返回值变为2,所以最后的打印为2,后面的值覆盖了前面的值,而最后打印调用的是被覆盖的值。

四.final和finalize的区别;

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

finally用的时候需要注意的:

(1)不要在fianlly中使用return。
(2)不要在finally中抛出异常。
(3)减轻finally的任务,不要在finally中做一些其它的事情,finally块仅仅用来释放资源是最合适的。
(4) 将尽量将所有的return写在函数的最后面,而不是try … catch … finally中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值