Java反射-泛型的本质

来源:互联网 发布:java上传压缩包 编辑:程序博客网 时间:2024/06/06 20:28

Class类的使用

类是java.lang.class类的实例对象(称为类类型 class type),而这个实例对象有三种表示方式

-第一种表达方式:任何一个类都有一个隐含的静态成员变量

Class c1 = Foo.class;

-第二种表达方式:通过对象的getClass的方法获取

Class c2 = foo1.getClass();

-第三种表达方式:通过Class.forName()获取

Class c3 = null;
c3 = Class.forName(“类的全称”);

-c1/c2/c3都代表了class type ,一个类只可能是class类的一个实例对象

System.out.println(c1==c2);
System.out.println(c1==c3);
输出都为true

-可以通过类类型创建该类的实例对象(需要有无参数的构造方法)

Foo foo = (Foo)c1.newInstance();

动态加载类与静态加载类

-编译时刻加载的类为静态加载类,运行时刻加载的类为动态加载类
-new 创建对象的静态加载类,在编译时刻就需要加载所有可能使用到的类

静态加载时会加载所有可能用到的类,若部分类不存在则会报错

-通过Class.forName()获取类为动态加载

动态加载时按需要加载,若用到的类不存在则报错
动态加载时要通过接口来实现加载(软件小规模的在线升级往往是对实现了接口的类进行修改)

方法的反射

Class基本API

-获取类的class type

Class c = obj.getClass();

-获取类的名称

c.getName();

-获取方法(获取了包括父类的方法)

Method[] ms = c.getMethods();

-获取方法(自己声明的方法,不包括父类的方法)

Method[] ms = c.getDeclaredMethods();

-得到方法的返回值类型的class type

ms[i].getReturnType();

-获取方法名

ms[i].getName();

-获取方法参数类型(得到参数类的class type)

Class[] paramType = ms[i].getParamTypes();

-方法的反射小demo

A a1 = new A();Class c = a1.getClass();// Method m = c.getMethod("print",new Class[]{int.class,int.class});Method m = c.getMethod("print",int.class,int.class});// 没有返回值返回null,有返回值返回具体的返回值Ocject obj = m.invoke(a1,new Object[]{10,20});// 下面的代码等同于上面Ocject obj = m.invoke(a1,10,20);
class A{    public void print(int a , int b){        System.out.println(a+b);    }    public void print(String a , String b){        System.out.println(a.toUpperCase()+b.toLowerCase());    }}

成员变量的反射

-获取public成员变量的信息

Field[] fs = c.getFields();

-获取该类自己声明的成员变量的信息

Field[] fs = c.getDeclaredFields();

-获得成员变量的class type

Class fieldType = field.getType();
String typename = fieldType.getName();

-获得成员变量的名称

String fieldName = field.getName();

构造函数的反射

-构造函数也是对象
-java.lang.Constructor中封装了构造函数的信息

获取所public得构造方法

Constructor[] cs = c.getConstructors();

获取自己声明的构造方法

Constructor[] cs = c.getDeclaredConstructors();

获得构造函数的参数列表的classtype

Class[] paramTypes = cs.getParameterTypes();

通过Class,Method来认识泛型本质

-集合的泛型是防止进行错误输入的
-但泛型的本质是相同的
-Java的泛型为伪泛型
-一个类只可能是class类的一个实例对象

ArrayList list = new ArrayList();ArrayList<String> list1 = new ArrayList<String>();list1.add("hello");//list1.add(20);该句会报错Class c1 = list1.getClass();Class c2 = list1.getClass();System.out.println(c1==c2);

-打印结果为true
-反射的操作都是编译以后的操作,在运行时刻执行的
-c1/c2的结果返回为true说明编译后的结果是去泛型化的
-Java中的泛型的是防止错误输入的,只在编译阶段有效,绕过编译就无效了
-可通过方法的反射操作绕过编译进行操作
-以下为验证代码

Method m = c2.getMethod("add",Object.class);m.invoke(list1,100);System.out.println(list);

-代码输出[hello,100]
-说明绕过编译即可绕过泛型
-不可同foreach遍历,因为进行遍历时会以String类型进行遍历会抛出异常

0 0