Java--异常、反射

异常

java.lang.Throwable:

Throwable:可抛出的。

    |--Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。

    |--Exception:异常,可以有针对性的处理方式

这个体系中的所有类和对象都具备一个独有的特点;就是可抛性。可抛性的体现:就是这个体系中的类和对象都可以被throws和throw两个关键字所操作。

throw与throws区别:

throws是用来声明一个方法可能抛出的所有异常信息,而throw则是指抛出的一个具体的异常类型。此外throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。

throw用于抛出异常对象,后面跟的是异常对象;throw用在函数内

throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在函数上

throw就是自己进行异常处理,处理的时候有两种方式,要么自己捕获异常(也就是try catch进行捕捉),要么声明抛出一个异常(就是throws 异常~~)。

定义异常处理时,什么时候定义try,什么时候定义throws呢?

功能内部如果出现异常,如果内部可以处理,就用try;

如果功能内部处理不了,就必须声明出来,让调用者处理。使用throws抛出,交给调用者处理。谁调用了这个功能谁就是调用者;

自定义异常的步骤:

1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性(既可以使用throw和throws去调用此类)。

2:通过throw 或者throws进行操作。

反射

反射技术:其实就是动态加载一个指定的类,并获取该类中的所有的内容。并将字节码文件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。

反射的基本步骤:

1、获得Class对象,就是获取到指定的名称的字节码文件对象。

2、实例化对象,获得类的属性、方法或构造函数。

3、访问属性、调用方法、调用构造函数创建对象。

内部类

如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,直接将A类定义在B类中。就可以了。A类就称为内部类。
  内部类可以直接访问外部类中的成员。而外部类想要访问内部类,必须要建立内部类的对象。

当内部类定义在外部类中的成员位置上,可以使用一些成员修饰符修饰 private、static。
  1:默认修饰符。
  直接访问内部类格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象;
  Outer.Inner in = new Outer.new Inner();//这种形式很少用。
  但是这种应用不多见,因为内部类之所以定义在内部就是为了封装。想要获取内部类对象通常都通过外部类的方法来获取。这样可以对内部类对象进行控制。
  2:私有修饰符。
  通常内部类被封装,都会被私有化,因为封装性不让其他程序直接访问。
  3:静态修饰符。
  如果内部类被静态修饰,相当于外部类,会出现访问局限性,只能访问外部类中的静态成员。
  注意;如果内部类中定义了静态成员,那么该内部类必须是静态的。

反射的用法:

1)、需要获得java类的各个组成部分,首先需要获得类的Class对象,获得Class对象的三种方式:

   

 Class.forName(classname)     用于做类加载

 obj.getClass()               用于获得对象的类型

 类名.class                 用于获得指定的类型,传参用

2)、反射类的成员方法:

Method[] methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。

Method[] methods = clazz.getDeclaredMethods();//获取本类中的方法,包含私有方法。

 method.setAccessible(true); 
{
 Class clazz = Person.class;
 Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});
    method.invoke();
}

3)、反射类的构造函数:

Constructor[] constructors = clazz.getConstructors();//只包含公共的

        constructors = clazz.getDeclaredConstructors();//包含私有的

{
    Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...})
    con.newInstance(params...)
}

4)、反射类的属性:

   Field field = clazz.getField(fieldName);

    field.setAccessible(true);

    field.setObject(value);

局部内部类:

内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。
  当内部类被定义在局部位置上,只能访问局部中final修饰的局部变量。

匿名内部类(对象):

没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。
  匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。

匿名内部类的使用场景:

当函数的参数接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。

题目:

    //1
        new Object(){
            void show(){
                System.out.println("show run");                
            }
        }.show();                                    //写法和编译都没问题
        //2
        Object obj = new Object(){
            void show(){
                System.out.println("show run");
            }
        };
        obj.show();                                //写法正确,编译会报错
        
        1和2的写法正确吗?有区别吗?说出原因。
        写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象。
        区别:
        第一个可是编译通过,并运行。
        第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了Object类型,而编译时会检查Object类中是否有show方法,此时编译失败。

猜你喜欢

转载自www.cnblogs.com/RobertLionLin/p/11484417.html