反射

来源:互联网 发布:导出数据库命令 编辑:程序博客网 时间:2024/06/11 04:18

反射

反射的操作是编译之后的操作---运行时刻的操作,所有下边方法的反射,变量的反射都是绕过编译,在运行时刻来执行的。 

Class类的使用

  • 一个类也属于对象,它是java.lang.Class类的对象
public class Foo {    public void print(int a,String b){        System.out.println("....");    }    public  static void main(String []args){        Foo foo1=new Foo();    }}

Class类的实例变量的表示<以上面的代码为例>
* Class c1=Foo.class;//这个代码也告诉我们,任何一个类都有一个隐含的静态成员变量class。
* Class c2=foo1.getClass();//已知该类的对象,通过getClass()方法来获取
* Class c3=null;
c3=Class.forName(“包名+类名”);

c1、c2、c3是Foo类的类类型,且c1=c2,c2=c3因为一个类只可能是Class类的一个实例变量。

我们可以通过(类类型)c1、c2、c3来创建Foo类的实例
Foo foo2=c1.newInstance();//前提是要有无参数的构造方法,因为通过这种方式创建类的对象时,它会默认去调用无参数的构造方法。

方法的反射

Method类,方法对象,一个方法就是一个Method对象。
方法的反射使用
* 获取方法:

Class c1=foo1.getClass();
Method[] ms=c1.getMethods();

getMethods()方法可以获取到所有的public方法,包括由父类继承而来的方法。
getDeclaredMethods()方法可以获取到该类自己声明的所有方法,不包含由父类继承而来的方法,不问访问权限。
getMethod()方法可以获取到public方法,包括由父类继承而来的方法。里边有两个参数(方法名,参数列表)

Method m=c1.getMethod("print",Class[]{int.class,String.class});

getDeclaredMethod()方法可以获取到该类自己声明的方法,不包含由父类继承而来的方法,不问访问权限。里边有两个参数(方法名,参数列表)
* 方法的反射操作
在使用反射之前,我们调用一个方法,通常都是这样来实现的:

foo1.print(6,"a");

在反射中,我们应该这么来做:

Method m=c1.getMethod("print",new Class[]{int.class,String.class});
Object o=m.invoke(foo1,new Object[]{6,"a"});//方法如果没有返回值,则返回空,如果有返回值,则返回具体的返回值。

成员变量的反射

成员变量的反射使用

Class c1=foo1.getClass();Field[] fd=c1.getFields();

getFields()方法可以获取到所有的public变量
getDeclaredConstructors()方法可以获取到该类自己声明的所有构造方法

构造函数的反射

构造函数的反射使用

Class c1=foo1.getClass();Constructor[] cs=c1.getConstructors();

getConstructors()方法可以获取到所有的public构造方法
getDeclaredFields()方法可以获取到该类声明的所有变量

通过Class,Method了解泛型的本质

一般情况下,我们进行集合的元素添加时都会经历编译时期。而编译之后,集合的泛型是去泛型化的。

去泛型化:

ArrayList list=new ArrayList();ArrayList<String> list1 = new ArrayList<>();Class c1=list.getClass();Class c2=list1.getClass();System.out.println(c1=c2);//结果为true
ArrayList list=new ArrayList();ArrayList<String> list1 = new ArrayList<>();list1.add(20);//这里会有错误,类型错误

而如果我们通过方法的反射来绕过编译时期:

ArrayList list=new ArrayList();ArrayList<String> list1 = new ArrayList<>();Class c1=list1.getClass()Method m=null;try {   m = c1.getMethod("add", Object.class);   m.invoke("add",20);//这样就绕过了编译}catch (Exception e){   e.printStackTrace();}

就可以将”20”添加到list1中了。

动态加载类

  • 静态加载:编译时刻加载类
  • 动态加载:运行时刻加载类–Class.forName()方法就包含了动态加载类

静态加载
通过new 来创建对象,是静态加载类,在编译时刻就需要加载所有可能用到的类。

动态加载
Class c4=double.class;//double数据类型的类类型
Class c5=Double.class;//Double类的类类型

类类型
基本数据类型都包含类类型
Void关键字同样具有类类型

1 0
原创粉丝点击