反射

反射

反射的操作是编译之后的操作---运行时刻的操作,所有下边方法的反射,变量的反射都是绕过编译,在运行时刻来执行的。 
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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值