反射和泛型的复习

反射

在框架的设计中很多都用到了反射,比如spring中我们在applicationContext.xml中配置类,通过反射+工厂模式得到类的实例,就可以操作类了——操作一个类可以分为操作属性,构造方法,普通方法。

反射的原理

我们编写的Java文件是xxx.java保存在硬盘上的,只是.java是无法运行的,需要编译成.class文件,JVM再将这个class文件通过类加载器加载到内存中,这个class文件在内存中是以Class类的形式表示。所以,使用反射的第一步是得到Class类(因为.java文件和没有加载到内存的.class文件计算机都是无法操作的),得到Class类就可以操作类的内容了(属性,构造方法,普通方法)

属性类:Field    构造方法类:Constructor  普通方法类:Method

获得Class类

方法一:类名,class

Class clazz1=Person.class;

方法二:实例.getClass()

Class clazz2=new Person().getClass();

方法三:Class.forName("类的全路径")     最常用

Class clazz3=Class.forName("cn.lynu.model.Person");

实例化对象

如果不使用new的方式,如何获得一个类的实例化?  那就是使用反射的newInstance()方法

Class clazz3=Class.forName("cn.lynu.model.Person");
Person person=(Person)clazz3.newInstance();

使用反射操作无参构造

    /**
     * 反射操作无参构造函数
     * @throws Exception
     */
    @Test
    public void fun1() throws Exception{
        Class clazz = Class.forName("cn.lynu.model.Person"); //得到class类
        Person p1 = (Person) clazz.newInstance();          //通过反射得到实例
        p1.setName("lz");
        System.out.println(p1.getName());
    }

这里我通过反射得到Person类的实例p1,通过p1给Name属性赋值

使用反射操作有参构造

主要使用的是getConstructor(构造方法参数的Class类)获得Constructor类,再通过Constructor类实例化,实例化的过程就可以给值了

    /**
     * 反射操作有参构造函数
     * @throws Exception
     */
    @Test
    public void fun2() throws Exception{
        Class clazz = Class.forName("cn.lynu.model.Person");
        //使用getConstructor(可变参数 参数类型的class类)得到构造函数类
        Constructor constructor = clazz.getConstructor(String.class,int.class);
        Person p2 = (Person) constructor.newInstance("lz",21);
        System.out.println(p2.getName()+" "+p2.getAge());
    }

使用反射操作属性

主要使用的是getDeclaredField("属性名")得到Field类,通过Field类设置属性的值(set()方法),对了,不要忘了使用 setAccessible(true); 就可以操作私有的属性(属性一般都是私有的)

    /**
     * 反射操作属性
     * @throws Exception
     */
    @Test
    public void fun3() throws Exception{
        Class clazz = Class.forName("cn.lynu.model.Person");
        //通过getDeclaredField(属性名)得到属性类
        Field age = clazz.getDeclaredField("age");
        //私有属性需要设置setAccessible(true),必须在设置参数之前
        age.setAccessible(true);
        //反射实例化对象
        Person p3 = (Person) clazz.newInstance();
        age.set(p3, 21);  //设置参数
        //System.out.println(name.get(p3));
        System.out.println(p3.getAge());
    }

使用反射操作普通方法

主要使用getDeclaredMethod("方法名","参数Class类")获得Method类,再通过Method类的invoke()方法给方法赋值。如果操作的是私有的方法也需要设置setAccessible(true); 。当操作的是静态的方法时候,因为静态方法调用的方式是 类名.方法名,所以使用反射操作静态方法的时候不需要实例  m1.invoke(null,"lz");

    /**
     * 反射操作普通函数
     * @throws Exception
     */
    @Test
    public void fun4() throws Exception{
        Class<?> clazz = Class.forName("cn.lynu.model.Person");
        //使用getDeclaredMethod(方法名,方法参数Class类)得到方法类
        Method name = clazz.getDeclaredMethod("setName", String.class);
        Person p4 = (Person) clazz.newInstance();   //反射实例化
        name.invoke(p4, "lz");     //给普通方法设置参数
        System.out.println(p4.getName());
    }

泛型

泛型多用于集合之上,例如这样的场景:将一个字符串类型的值放入到集合中,这个值就会失去其类型,统一为Object类型,而后再将这个值取出进行类型转换,就容易出现类型转换异常,因为Object可以转换为任何类型,要解决这样的问题就需要使用泛型

泛型语法

一般情况下我们使用T表示泛型,但这不是强制要求。注意:给这个T赋具体类型的时候要使用基本类型的包装类

  1. 在集合上使用  集合<具体类型>
  2. 在返回值和形参上使用
  3. 在类上使用 class A<T>
  4. 在方法上使用 public <T> void fun1(T t1){}      public <T> T fun2(T t1,T t2){}
  5. 在局部变量(因为要使用T,就需要在已定义过的地方,所以可以在泛型方法和泛型类的成员属性使用)上使用
public <T> void fun1(){
        T abc;
}

class a<T>{
        T bcd;
}

泛型的使用

下面是一个使用泛型进行数组元素颠倒顺序的例子,使用泛型增加了通用性

import java.util.Arrays;

public class TestDemo3 {

    public static void main(String[] args) {
        Integer[] arr1={1,2,3,4,5,6};
        System.out.println(Arrays.toString(arr1));
        reverse(arr1);
        System.out.println(Arrays.toString(arr1));
        System.out.println("==================");
        String[] arr2={"aaa","bbb","ccc","eee","fff"};
        System.out.println(Arrays.toString(arr2));
        reverse(arr2);
        System.out.println(Arrays.toString(arr2));
    }

    /**
     * 使用泛型颠倒数组元素
     */
    public static <T> void reverse(T[] arr){
        for(int i=0;i<(arr.length/2);i++){
            T temp=arr[i];
            arr[i]=arr[arr.length-1-i];
            arr[arr.length-1-i]=temp;
        }
    }

}

reverse()方法使用泛型,所以我们不管数组到底是什么类型的,都可以完成元素的颠倒操作

区分泛型类中的方法和泛型方法

泛型类中的方法:

class A<T>{
  public T fun1(T t1){}       //不是泛型方法,只是泛型类中的一个方法
}

泛型方法:

public <T>  T fun1(T t1){}        //泛型方法

这俩个fun1方法表达意思是不一样的,泛型方法与泛型类没什么关系,泛型方法不一定要在泛型类中,泛型类中也不一定都是泛型方法

泛型的继承和实现

泛型可以认为不可以继承,子类不是泛型类:

class A<T>{}

class AA1 extends A<String>  {}        //这个AA1不是泛型类,只是其父类A是泛型类

这个例子中AA1不是泛型类,只是其父类泛型类,AA1在声明的时候需要指定父类泛型的具体类型

子类是泛型类 :

class A<T>{}

class AA2<T> extends A<T> {}          //子类也是泛型类

这里子类AA2是泛型类,继承的父类A也是泛型类,子类也是泛型类情况下,可以实例化AA2的时候再指明泛型的具体类型

public class TestDemo5{
    public static void main(String[] args) {
        AA1 aa1=new AA1();
        aa1.fun2(t1);        //t1为Integer类型

        AA2<String> aa2=new AA2<String>(); //泛型类在实例化时指定类型
        aa2.fun2(t1);        //t1为String类型
    }
}

class A<T>{

    private T ab;

    public void fun1(){}

    public void fun2(T t1){}

    public void fun3(T t1,T t2){}
}

class AA1 extends A<Integer>{     //继承于泛型类A,AA1不是泛型类

}

class AA2<T> extends A<T>{        //继承于泛型类A,AA2是泛型类

}
时间: 2024-10-14 06:20:08

反射和泛型的复习的相关文章

基于反射和泛型的编程

基于反射和泛型的编程,泛型是容器话的思路统过泛型对象或泛型方法,管理实际 要操作的对象,以实现对于实际对象管理的一种编程. 比如导出excel生成报表这种在平台开发中及其普遍的需求,有多个对象有生成报表 的需求如每个对象编写生成excel逻辑,程序会变得异常复杂,重复逻辑众多,通过将导 出excel逻辑泛型化,需要生成excel的bean本身不需要做任何变化,就可以按照需求生 成对应报表,这是一种很优雅很方便的报表生成方式.

DataTable转任意类型对象List数组-----工具通用类(利用反射和泛型)

public class ConvertHelper<T> where T : new() { /// <summary> /// 利用反射和泛型 /// </summary> /// <param name="dt"></param> /// <returns></returns> public static List<T> ConvertToList(DataTable dt) { //

java反射+java泛型,封装BaseDaoUtil类。供应多个不同Dao使用

当项目是ssh框架时,每一个Action会对应一个Service和一个Dao.但是所有的Ation对应的Dao中的方法是相同的,只是要查的表不一样.由于封装的思想,为了提高代码的重用性.可以使用java中的泛型+反射去实现最终的封装,将所有的Dao层的共同部分写一个BaseDaoUtil.而所有的Dao都继承这个类. 思路: ----->(1)反射+泛型 ----->(2)当生成子类对象(UserDao),调用空构造时(new UserDao()),子类的空构造会默认调用父类的空构造器(new

List转DataTable(反射) ; 将泛型集合类转换成DataTable ; 将集合类转换成DataTable

#region 将集合类转换成DataTable /// <summary> /// 将集合类转换成DataTable /// </summary> /// <param name="list">集合</param> /// <returns></returns> public static DataTable ToDataTable(IList list) { DataTable result = new Dat

通过反射获取泛型信息

1 package com.coscon.reflectionTest; 2 3 import java.lang.reflect.Method; 4 import java.lang.reflect.ParameterizedType; 5 import java.lang.reflect.Type; 6 import java.util.List; 7 import java.util.Map; 8 9 //用过反射获取泛型信息 10 public class ReflectionForGe

java 反射 子类泛型的class

很早之前写过利用泛型和反射机制抽象DAO ,对其中获取子类泛型的class一直不是很理解.关键的地方是HibernateBaseDao的构造方法中的 [java] view plaincopy Type genType = getClass().getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); entityClass =  (Class)params[0]

使用反射为泛型集合添加其他类型的数据时遇到的问题

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合进会去掉“类型”信息,使程序运行效率不受影响. 由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合虽加入其它类型的数据. 所以我们可以用反射为泛型集合添加其他类型的数据. 例1: ArrayList<Integer> arrayList = new ArrayList<Integer>(); arrayList .add(10); a

利用反射,泛型,静态方法快速获取表单值到Model

在项目中经常需要处理表单,给model赋值,很烦人的一些重复代码.如下边的代码: News news = new News(); news.Id = int.Parse(Request.Form["Id"]); news.Category = int.Parse(Request.Form["Category"]); news.Title = Request.Form["Title"]; news.CreateTime = DateTime.Par

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理 2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论:0 | 浏览:45 | 该类在MVC中可以方便管理配置信息,可以直接把Model储存进数据库或者从数据库去除数据转为Model. 1 何为配置项目? 比如网站的名称,页脚信息,meta中的KeyWord信息等,如果不想硬编码到网页里,就需要使用配置文件进行储存,通常都是储存到数据库中.使用的时候读取出来