Java 异常与反射 总结

      1.异常  

        异常,简单来讲,就是一个程序执行过程当中发生的不正常状况的事件。它发生在程序的运行期间,干扰了正常的指令流程。若是没有处理异常,那么出现异常以后,程序会中止运行。异常分为运行异常和非运行异常。非运行异常也叫编译异常。对于编译异常编译器要求必须处理。不然没法运行。运行时异常编译器不要求强制处理。运行时异常通常是由程序逻辑错误引发的,程序应该从逻辑角度尽量避免这类异常的发生。它们都继承于Exception类。运行异常和非运行异常也下分各种异常。异常发生的缘由是程序错误或偶然的外在因素致使的通常性问题。html

继承关系如图java

若是一个方法内抛出异常,该异常会被抛到调用方法中。若是异常没有在调用方法中处理,它继续被抛给这个方法的调用者。这个过程将一直继续下去,直到异常被处理。这一过程称为捕获异常。api

2.反射

在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;框架

对于任意一个对象,都可以调用它的任意一个方法和属性;ide

这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。函数

反射的思惟导图以下工具

 

 

      当使用反射时候,首先须要获取到Class类的对象,获得了这个类以后,就能够获得class文件里面的全部内容。google

如下是具体的反射应用方式spa

1.类型转换:将Map转成Person的示范

Person类是一个普通的实体类,里面包含三个私有的成员属性及它们的Set和Get函数。Map是集合框架里使用的Map类型框架,里面能够加入泛型。具体转换代码以下3d

 1 //param1:要转化的数据类型Person.class        String.class
 2 public static Object toBean(Class<?> type,Map<String,? extends Object> map) throws Exception{
 3     
 4     //Introspector专门处理Bean的工具类。好比获取Class的属性或者方法或构造
 5     BeanInfo beanInfo = Introspector.getBeanInfo(type);//参数传递的就是类的类型
 6     //调用newInstance方法建立这个类
 7     Object o = type.newInstance();
 8     //获取o的方法
 9     PropertyDescriptor[] ps = beanInfo.getPropertyDescriptors();
10     for (int i = 0; i < ps.length; i++) {
11 
12         PropertyDescriptor p = ps[i];
13         //获取方法描述的名称(属性名称)若是是Person --->name(name,age,sex)
14         String name = p.getName();
15         //name是否就是map中的key?
16         if(map.containsKey(name)){
17             //经过key获取map的值
18             Object value = map.get(name);
19             //经过反射,value赋给o
20             //p.getWriteMethod();//set方法
21             //p.getReadMethod();//get方法
22             p.getWriteMethod().invoke(o, value);
23         }
24     }
25     //获取map中的key的值,以及value的值
26     return o;
27 }
28 public static void main(String[] args) throws Exception {    
29     Map pMap = new HashMap();
30     pMap.put("name", "张三");
31     pMap.put("age", 1);
32     pMap.put("sex", 2);
33     //Map--->Object
34     Person p = new Person("张三");
35     p.setAge(1);
36     p.setSex(2);
37     Person o = (Person)toBean(Person.class,pMap);
38     System.out.println(" "+o.toString());
39 }

        以上代码的思想就是,建立一个相对于想要的类的BeanInfo,而后经过这个BeanInfo对象获得全部的属性名称(对应到Map里就是全部键值对的键),而后判断Map里是否有与获取的键名称同名的键,若是有的话就经过Map获取那个键的值,而后经过PropertyDescriptor对象获取须要的对象的set方法,将值赋值给相应的属性,最后返回相应的类型的对象。

2.Java中五种建立新对象的方法

 1>直接用new调用该类的构造函数

new Person("张三");

2>使用class类中的newInstance方法建立对象,调用构造函数

1 public static void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
2         //一、获取Class类的对象    
3         Class c = Class.forName("com.Person");
4         //二、经过Class类中的newInstance方法建立Person对象
5         Person p = (Person)c.newInstance();
6         //三、检测一下
7         p.setName("张三");
8         System.out.println(p.getName());
9     }

3>使用class类型中的构造函数中的newInstance方法

public static void test2() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        //一、获取Person类型
        Constructor c = Person.class.getConstructor();
        //二、建立方法
        Person p = (Person)c.newInstance();
        //三、检测
        p.setName("张三");
        System.out.println(p.getName());
    }

4>经过clone方法建立。前提是须要在实体类里重写clone()方法

/** *实体类 **/
public class Person implements Cloneable{ private String name; private int age; private int sex; @Override protected Person clone() throws CloneNotSupportedException { Person person = null; person = (Person)super.clone(); return person; } } /** *功能类中clone功能函数 **/
public static void test3(){ //须要重写clone方法,重写cloneable接口。很是特殊 //在Person类里实现cloneable接口
        Person p1 =new Person("王五"); //调用clone方法建立一个新的对象p2
        Person p2 = null; try { p2 = p1.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } System.out.println(p1==p2); }

5>序列化和反序列化的方法,经过这种方法能够将对象转换为字节序列的方式,把对象传输到另外一台机器上。

3.经过反射获取方法和操做属性

1>经过反射获取方法

经过反射获取方法的方式是先申明一个Class对象,而后经过该对象的getDeclaredMethod方法建立Method对象,经过Method对象的invoke方法调用获取到的方法实现功能。具体示例代码以下

 1 public static void test5() {
 2         try { 
 3             Class c = Class.forName("com.hpe.ref.Person");
 4             //获取方法        Person setName  getName
 5             //param1:方法名的String类型
 6             //param2:方法的参数类型
 7             Method m = c.getDeclaredMethod("setName", String.class);
 8             //建立Object对象
 9             Object obj = c.newInstance();
10             //invoke调用方法(反射的方式调用方法)
11             //param1:反射的类,param2:m方法的值
12             m.invoke(obj, "张三");
13             //验证
14             Method gM =c.getDeclaredMethod("getName");
15             System.out.println(gM.invoke(obj));
16         } catch (Exception e) {
17             // TODO Auto-generated catch block
18             e.printStackTrace();
19         }
20     }

2>经过反射获取属性

        经过反射获取属性的方法是经过Class获取该对象的Class对象形式,以后经过Field以字符串的形式获取类中的属性,而后经过Field对象来操做该属性。具体代码以下。

public static void test4(){
        //经过反射,在运行阶段建立这个person对象
        try {
            Class c = Class.forName("com.hpe.ref.Person");
            
            Field field = c.getDeclaredField("name");
            //经过字符串的形式获取类中的属性。
            Field[] fs = c.getDeclaredFields();
            //设置对属性,若是是私有的,能够有权限访问
            field.setAccessible(true);
            Object o  =c.newInstance();
            //set方法----操做属性的方式
            field.set(o, "张三");
            System.out.println(field.get(o));
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

3.小注:分析下列代码功能

段代码的功能分析

public int indexOf(int ch)

返回指定字符第一次出现的字符串内的索引。 若是与值的字符ch在此表示的字符序列发生String第一事件发生之对象,则索引(在Unicode代码单元)被返回。

public StringBuffer insert(int offset, char c)

在此序列中插入char参数的字符串表示形式。

整体效果就好像第二个参数经过方法String.valueOf(char)转换为一个字符串,而且该字符串中的字符而后是inserted到指定的偏移量的这个字符序列。

offset参数必须大于或等于0 ,小于或等于该序列的length

因此它的功能是,以小数点为界,每往前数三位,就在str字符串里插入一个逗号。以达到计算数字的位数效果。

相关文章
相关标签/搜索