Java基础增强3-反射,内省,beanutils,泛型

来源:互联网 发布:淘宝网购物女装牛仔裤 编辑:程序博客网 时间:2024/05/16 01:07

1、反射(reflect):(利用配置文件)

反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。主要应用于框架,框架基于配置文件。

加载类:

        //加载类的字节码        //1  常用        Class classz1 = Class.forName("seu.xinci.reflect.person");        //2        Class classz2 = Person.class;        //3        Class callsz3 = new Person().getClass();

解剖类:

得到public:
Constructor getConstructor
Method getMethod
Field getField

得到private:
Constructor getDeclaredConstructor
Method getDeclaredMethod
Field getDeclaredField

获得构造方法:


    @Test  //反射类无参的构造方法 public Person()    public void test1() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {        //利用Constructor创建对象        Class classz = Class.forName("seu.xinci.reflect.Person");        Constructor constructor = classz.getConstructor();        Object o = constructor.newInstance(null);        System.out.println(o);    }

    @Test  //反射类有参的构造方法 public Person(String name)    public void test2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {        //利用Constructor创建对象        Class classz = Class.forName("seu.xinci.reflect.Person");        Constructor constructor = classz.getConstructor(String.class);   //制定参数类型,不是变量名称        Person o = (Person) constructor.newInstance("aa");        System.out.println(o);    }
    @Test  //反射类私有的、有参的构造方法 private Person(int name)    public void test3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {        //利用Constructor创建对象        Class classz = Class.forName("seu.xinci.reflect.Person");        Constructor constructor = classz.getDeclaredConstructor(int.class);   //制定参数类型,不是变量名称        constructor.setAccessible(true);    //暴力反射        Person o = (Person) constructor.newInstance(25);        System.out.println(o);    }

获得构造方法:

//反射无参    public void eat()    @Test    public void test() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Class classz = Class.forName("seu.xinci.reflect.Person");  //带包的名称:完整名称        Person person = (Person) classz.newInstance();        Method eat = classz.getMethod("eat", null);        eat.invoke(person,null);    }

<pre name="code" class="java">//反射有参    public void run(String address)    @Test    public void test2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");  //带包的名称:完整名称        Method eat = classz.getMethod("run", String.class);        eat.invoke(person,"北京");    }
</pre><pre>
    //反射有参带返回值    public String test(String string)    @Test    public void test3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");  //带包的名称:完整名称        Method eat = classz.getMethod("test", String.class);        String cs = (String) eat.invoke(person, "北京");        System.out.println(cs);    }

    //反射有参带返回值、私有方法    private String test2(String string)    @Test    public void test4() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");  //带包的名称:完整名称        Method eat = classz.getDeclaredMethod("test2", String.class);        eat.setAccessible(true);    //暴力反射        String cs = (String) eat.invoke(person, "北京");        System.out.println(cs);    }

    //反射有参带返回值、静态方法    public static String test3(String string)    @Test    public void test5() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");  //带包的名称:完整名称        Method eat = classz.getDeclaredMethod("test3", String.class);        String cs = (String) eat.invoke(null, "北京");        System.out.println(cs);    }

    //反射mian方法  public static void main(String[] args)    //通过反射调用带数组的方法时,要注意处理    @Test    public void test6() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");  //带包的名称:完整名称        Method eat = classz.getDeclaredMethod("main", String[].class);        eat.invoke(null, (Object) new String[]{"1","2"});    }
传一个数组容易出问题,因此,如果只传一个数组那么就要欺骗。(Object)

获得反射成员变量:

    //反射类的字段  ---set   public String name;    @Test    public void test1() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");        Field name = classz.getField("name");        name.set(person,"fix");        System.out.println(person.getName());    }

    //反射类的字段  ---get   public String name;    @Test    public void test2() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {        Person person = new Person();        person.setName("xxx");        Class classz = Class.forName("seu.xinci.reflect.Person");        Field name = classz.getField("name");        String o = (String) name.get(person);        System.out.println(o);    }

final类型的变量,设置了就不能修改了。
    //反射类的字段  ---set    private int age;    @Test    public void test3() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {        Person person = new Person();        Class classz = Class.forName("seu.xinci.reflect.Person");        Field name = classz.getDeclaredField("age");        name.setAccessible(true);        name.set(person,123);        System.out.println(person.getAge());    }

    //反射类的字段  ---get    private int age;    @Test    public void test4() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {        Person person = new Person();        person.setAge(123);        Class classz = Class.forName("seu.xinci.reflect.Person");        Field age = classz.getDeclaredField("age");        age.setAccessible(true);        int o = (Integer) age.get(person);        System.out.println(o);    }

2、内省(introspector):

用于操作javabean对象。
有什么get、set方法就有什么属性。
  1. 直接调用bean的setXXX或getXXX方法。
  2. 通过内省技术访问(java.beans包提供了内省的API),内省技术访问也提供了两种方式。
  • 通过PropertyDescriptor类操作Bean的属性
  • 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。


    //通过内省api操作bean的name属性    @Test    public void test1() throws IntrospectionException, InvocationTargetException, IllegalAccessException {        Student s = new Student();        PropertyDescriptor pd = new PropertyDescriptor("name",Student.class);        Method writeMethod = pd.getWriteMethod();        writeMethod.invoke(s,"flx");        //System.out.println(s.getName());        Method readMethod = pd.getReadMethod();        String result = (String) readMethod.invoke(s, null);        System.out.println(result);    }

类继承object,object中有getClass(),所以会有class属性

    //操作bean的所有属性    @Test    public void test2() throws IntrospectionException {        BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);        PropertyDescriptor[] pd = beanInfo.getPropertyDescriptors();        for (PropertyDescriptor is:pd){            System.out.println(is.getName());        }    }

3、BeanUtils:

Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。

所需文件:beanutils(commons-beanutils-1.9.2.jar),log4j(commons-logging.jar)    (Apache公司)

实例:

 //用beanUtils操作bean    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {        Student s = new Student();        BeanUtils.setProperty(s, "name", "flx");        System.out.println(s.getName());    }
自动的类型转换!  例如下面例子中的age字段!!////以下代码中的birthday是错误示例!!!

    //用beanUtils操作bean    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {        String name = "flx";        String password = "123";        String email = "flx@sina.com";        String age = "21";        String birthday = "1990-09-19";        Student s = new Student();        BeanUtils.setProperty(s, "name", name);        BeanUtils.setProperty(s, "password", password);        BeanUtils.setProperty(s, "email", email);        BeanUtils.setProperty(s, "age", age);        BeanUtils.setProperty(s, "birthday", birthday);        System.out.println(s.getAge());        System.out.println(s.getBirthday());    }

可以自动进行8中基本类型的转换。但是birthday这种String类型的转换就不可以实现。

除了 这四类八种基础类型,剩下的java 一切类型 都是引用类型。那么 这四类八种基础数据类型是什么呢? 请看下面

第一类:整型 byte short int long

第二类:浮点型 float double

第三类:逻辑型 boolean(它只有两个值可取true false)

第四类:字符型 char

示例:ConverUtils   注册转化器!!!

 //用beanUtils操作bean    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {        String name = "flx";        String password = "123";        String email = "flx@sina.com";        String age = "21";        String birthday = "1990-09-19";        Student s = new Student();        ConvertUtils.register(new DateLocaleConverter(),Date.class);        BeanUtils.setProperty(s, "name", name);        BeanUtils.setProperty(s, "password", password);        BeanUtils.setProperty(s, "email", email);        BeanUtils.setProperty(s, "age", age);        BeanUtils.setProperty(s, "birthday", birthday);        System.out.println(s.getAge());        System.out.println(s.getBirthday());    }

不能new接口的原因是接口里面有抽象的方法,但是如果我们在new的时候把抽象的方法实现了,那么就可以了。

实现自己的Convert转换器:

//用beanUtils操作bean    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {        String name = "flx";        String password = "123";        String email = "flx@sina.com";        String age = "21";        String birthday = "1990-09-19";        Student s = new Student();        ConvertUtils.register(new Converter() {            public Object convert(Class type, Object value) {                if (value == null)                {                    return null;                }                SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd");                Date date = null;                try {                    date = formatter.parse((String) value);                } catch (ParseException e) {                    throw new ConversionException(e);                }                return date;            }        }, Date.class);        BeanUtils.setProperty(s, "name", name);        BeanUtils.setProperty(s, "password", password);        BeanUtils.setProperty(s, "email", email);        BeanUtils.setProperty(s, "age", age);        BeanUtils.setProperty(s, "birthday", birthday);        System.out.println(s.getAge());        System.out.println(s.getBirthday());    }

操作bean的属性优先选用beanUtils
对于8种基本类型,用自带转换器。如果实在没有找到,自己去写。

4、泛型(generic):

为了保证程序的安全性,最典型的应用场景就是集合。       <>念着typeof
JDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。
泛型是给编译器用的。
编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。 
整个ArrayList<Integer>称为参数化的类型ParameterizedType。
    //泛型典型应用1  单列    @Test    public void test1(){        List<Integer> list = new ArrayList<Integer>();        list.add(1);        int i = list.get(0);    }

取map集合一定用的是entryset()!!!
    //泛型典型应用2  双列    @Test    public void test2(){        Map<String,Integer> map = new LinkedHashMap<String, Integer>();        map.put("a",1);        map.put("aa",2);        Set<Map.Entry<String, Integer>> entries = map.entrySet();        for (Map.Entry<String, Integer> i:entries){            String key = i.getKey();            Integer value = i.getValue();            System.out.println(key + "=" + value);        }    }

使用泛型的注意事项:

  1. 使用泛形时,泛形类型须为引用类型,不能是基本数据类型。
  2. 定义变量只用对象,到底能调用什么方法由变量决定的。         一旦用到泛型,左右两边都应该一致,除非只用一边。
    //ArrayList<String> list = new ArrayList<Object>();   错误示例    //ArrayList<Object> list = new ArrayList<String>();   错误示例    ArrayList<String> list = new ArrayList ();    ArrayList list = new ArrayList<String>();

自定义泛型: 

1、编写一个泛型方法,交换数组上的任意两个的元素。
    public static void main(String[] args) {        Integer arr1[]={1,2,3};        swap(arr1,0,1);        System.out.println(Arrays.asList(arr1));        Byte arr2[]={'a','b','c'};        System.out.println(Arrays.asList(arr2));    }    //编写一个泛型方法,交换数组上的任意两个位置的元素  不能确定传入数组的类型    @Test    public static  <T> void swap (T arr[],int pos1,int pos2){        T temp = arr[pos1];        arr[pos1] = arr[pos2];        arr[pos2] = temp;    }
2、编写一个泛型方法,接收一个任意数组,并颠倒数组中的所有元素:
public class Demo2 {    public static void main(String[] args) {        Integer arr[] = {1,2,3,4};        swap(arr);        System.out.println(Arrays.asList(arr));    }    //编写一个泛形方法,接收一个任意数组,并颠倒数组中的所有元素    public static  <T> void swap (T arr[]){        int start = 0;        int end = arr.length-1;        while(start <= end)        {            T temp = arr[start];            arr[start] = arr[end];            arr[end] = temp;            start++;            end--;        }    }}
只有对象类型才能作为泛型方法的实际参数。
在泛型中可以同时有多个类型,例如:
public static <K,V> V getValue(K key) { return map.get(key);}

在类上面定义的泛型只对类的非静态成员有效!!         静态不需要进行new,也就不知道T
如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下:
public class GenericDao<T> {
private T field1;
public void save(T obj){}
public T getId(int id){}
}












0 0
原创粉丝点击