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

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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值