初识Java反射机制 总结

关于Java中的反射机制

1.初识反射机制

       在java中通过反射机制可以操作相关的字节码文件。如获取类文件,创建对象,调用方法等。
       与反射机制相关的类包括Class,Method,Constructor,Field等,其中Class类在java.lang包下,Method,Constructor,Field类在java.lang.reflect包下。本文内容主要围绕这几个类展开。

2.Class类

        获取Class的三种方式
       1.使用Class类中的 forName(String className) 方法,在使用该方法的时候有异常需要处理,参数需要填写完整类名,该方法返回一个相应的类,代码如下:

try {
	Class c = Class.forName("java.lang.String");
    System.out.println(c);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Class类的对象通过 s.getSimpleName() 可以获取简写的类名,如:

Class s = Class.forName("java.lang.String");
String name = s.getSimpleName();//name= String

       此外,如果遇到只需要让静态代码块执行的情况,可以用 froName() 方法,这种方式在JDBC中有用到。

       2.使用 getClass() 方法,所有的对象中都含有该方法,该方法继承于Object中。该方法会返回一个与对象相同的类,代码如下:

 String s = "abc";
 Class x = s.getClass();//x代表String.class

       3.任何一种类型,包括基本数据类型,都含有class属性,利用class属性也可以获得相应的类,代码如下:

Class z = String.class;//z代码String类型

       以上三种方式均可以得到String.class,并且其中c,x,z三个变量中的内存地址都是相同的,都指向同一个方法区的类文件。

3.Field属性

在java.lang.reflect包下有一个 Field 类,代表类中的属性。

获取类中的属性

       利用 Field 中的方法,我们可以获取到类中属性。通过 getFields() 方法可以获取到所有的public属性,该方法返回一个Field数组。

 Class s = Class.forName("java.lang.String");
 Field[] fields = s.getFields();//代表String类中的所有public属性

       但是该方法只能获得类中的public属性,如果在类中存在其他修饰符修饰的属性就无法获得。这个时候我们可以用 getDeclaredFields() 方法,该方法可以返回类中的所有属性,同样返回一个Field数组。

Class s = Class.forName("java.lang.String");
Field[] fields = s.getDeclaredFields();//代表String类中的所有属性
获取属性名,类型,修饰符列表

       我们可以通过对数组的遍历,拿到类中的每一个属性,并且可以通过 getName() 方法获取属性名:

Class s = Class.forName("java.lang.String");
Field[] fields = s.getDeclaredFields();
for(Field field : fields){
    String name = field.getName();//获取name
}

       通过 **getType()**方法获取属性类型 ,不过该方法返回的是一个Class,因为属性都是一种类型:

 Class s = Class.forName("java.lang.String");
 Field[] fields = s.getDeclaredFields();
 for(Field field : fields){
      Class type = field.getType();//获取type
}

       以及通过 getModifiers() 获取属性的修饰符列表。值得一提的是getModifiers() 方法返回的是一个int,我们需要通过Modifier类的toString()方法将其转换成相应的String。如下:

Class s = Class.forName("java.lang.String");
Field[] fields = s.getDeclaredFields();
for(Field field : fields){
    int i = field.getModifiers();
    String modifier = Modifier.toString(i);
}
获取指定的某个属性

       当我们需要获取类中指定一个属性的时,我们则可以使用 getDeclaredField(Sting name) 方法,该方法返回一个特定的Field。如:

Class s = Class.forName("com.Student");
Student stu = (Student) s.newInstance();
Field field = s.getDeclaredField("no");

       并且我们可以通过 set(Object obj, Object value)get(Object obj) 方法给对象属性赋值和读取。但是我们依然不能访问私有的属性,不过我们可以通过打破封装来访问私有属性,setAccessible(true)。 代码如下:

Class s = Class.forName("com.Student");
Student stu = (Student) s.newInstance();
Field field = s.getDeclaredField("name");//name是私有属性
field.setAccessible(true);//打破封装
field.set(stu,"mike");//设置属性值
System.out.println(field.get(stu));//读取属性值

4.Method方法

同样通过反射Method,我们可以获取一个类中方法的各种信息。

获取所有的Method

       同样我们可以通过对照Field中的方法学习Method的方法,getDeclaredMethods() 方法可以获得所有的Method方法,返回的是一个Method数组,我们可以通过遍历该数组取出每一个Method。

Class s = Class.forName("com.Student");
Method[] methods = s.getDeclaredMethods();
获取方法名,返回值类型,修饰符列表,参数列表

同样,getName() 可以获取方法的方法名:

Class s = Class.forName("com.Student");
            Method[] methods = s.getDeclaredMethods();
            for(Method method : methods){
                String name = method.getName();
            }

getReturnType() 可以得到方法的返回值类型:

Class s = Class.forName("com.Student");
            Method[] methods = s.getDeclaredMethods();
            for(Method method : methods){
                Class c = method.getReturnType();
            }

getModifiers() 可以获取修饰符列表,返回值类型依旧是int,可以调用Modifier的toString()方法将其转换。

Class s = Class.forName("com.Student");
Method[] methods = s.getDeclaredMethods();
for(Method method : methods){
	System.out.println(Modifier.toString(method.getModifiers()));
}

       在方法中一般都有参数,我们如何通过反射获取参数列表呢? getParameterTypes() 可以获取到方法的所有参数,并且返回的是一个Class数组,如果我们需要的话可以对Class数组进行操作。:

Class s = Class.forName("com.Student");
Method[] methods = s.getDeclaredMethods();
for(Method method : methods){
	Class[] classes = method.getParameterTypes();
}
调用方法

       与Field不同的是,确定一个Method不能只靠方法名,因为有可能在类中方法有重载。确定一个方法需要同时确定方法名以及方法的参数列表,那么我们该如何通过反射机制来调用方法呢?
首先我们需要获取一个类,在创建该类的对象,通过对象调用getDeclaredMethod(String name,Class… paramterType) 方法,通过传入方法名以及参数列表的类来获取某个方法。然后通过调用invoke(Object obj,Object… args) 方法,并且传入调用方法的对象以及需要的参数,来调用该方法。代码如下:

Class s = Class.forName("com.Student");
Student stu = (Student) s.newInstance();
Method method = s.getDeclaredMethod("speak",String.class);
//speak方法有一个String参数
method.invoke(stu,"lalala");

5.Construct构造方法

与上面相同,通过 getDeclaredConstructors() 可以获取所有的构造方法。 getModifiers() 可以获取修饰符列表。

通过反射机制创建对象

类调用 newInstance() 方法可以创建该类的无参构造方法。上面的例子中有多次用到。
如果需要调用有参构造方法,则需要调用 getDeclaredConstructor(Class… parameterTypes) 方法,传入相应的参数,获取该构造方法,再而通过调用 newInstance(Object… initargs) 方法,传入参数创建对象。

Class s = Class.forName("com.Student");
Constructor constructor = s.getDeclaredConstructor(int.class,String.class);
Object o = constructor.newInstance();//o是Student对象

6.获取父类和接口

getSuperclass() 方法返回该类的父类。
getInterfaces() 方法返回该类实习的接口,返回的是一个Class数组。

7.反射机制的作用

利用反射机制的灵活性相当高,我们可以将需要的资源信息写在properties文件中,在利用资源绑定器(ResourceBundle)读取文件中的信息,之后利用反射机制便可以做相应的操作。并且将信息写在properties中可以避免修改代码的操作,当信息有变化的时候,只需要修改properties文件中的信息便可以达到修改程序的作用。如我们在properties文件中写入 className=java.lang.String ,之后可以利用反射机制获取class:

ResourceBundle bundle = ResourceBundle.getBundle("class");
String className = bundle.getString("className");
try {
    Class c = Class.forName(className);
    System.out.println(c);//c表示String。class
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

当我们的信息需要改变时,我们不需要修改代码,只需要修改properties文件中的信息便可以达到修改程序的功能,所以非常的灵活。

  • 13
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值