我是靠谱客的博主 拼搏纸飞机,最近开发中收集的这篇文章主要介绍【Java进阶营】Java反射复习,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言
java反射技术是java中经常使用到的技术,并且有不少的开源框架都是会使用过反射。
虽然由于性能原因,目前在Android中的部分框架都已经采用了对性能影响更小的apt框架,但是java反射仍然是一个十分重要的概念与技术。

一、 java反射基本功能
首先我们说一下Java反射的概念:

在运行状态中,对于任意一个类,都能够获取到这个类的属性及方法;对于任意一个对象,能够调用其任意数的属性和方法。

这种能够在运行时动态获取类和对象信息的方式被称为Java语言的反射机制。

Java反射常用的内容功能包括如下几项(在运行时):

根据一个字符串得到一个类的对象
获取一个类的所有公有或私有、静态或者示例的字段、方法、属性。
二、基本使用

  1. getClass()
    可以使用getClass()方法通过一个对象获取其Class类,举例如下:

     String name = "Test";
    Class c1 = name.getClass();
    System.out.println(c1.getName());
    

结果是:

java.lang.String
2. Class.forName()
也可以通过一个类的详细名称来获取Class对象,如下:


String className= "java.lang.String";
Class c2 = null;
try{
c2 = Class.forName(className);
System.out.println(c2.getName());
}
catch (Exception e){
e.printStackTrace();
}

通过getSuperclass方法可以获取到对象的父类型。

此处采用try catch是因为自定义的className可能不合法,所有需要处理异常。

  1. Type属性
    基本类型都有type属性,可以得到这个基本类型的type:

Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
三、获得类成员

  1. 获得类的构造方法
    使用反射可以获得类的构造方法,包括私有和公有的方法,也智慧无参和有参这两种类型的构造方法。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
    举例来说,我们有一个TestClass类,有多个构造方法,其中既有公有方法也有私有方法,代码如下:

public class TestClass {

private int age;
private String name;
public TestClass(int age) {
this.age = age;
}
public TestClass(int age, String name) {
this.age = age;
this.name = name;
}
private TestClass(String name) {
this.name = name;
}
public TestClass() {
}
public void printData(){
System.out.println("age:"+age+"
name:"+name);
}

}
我们可以通过getDeclaredConstructors获得当前类的所有的构造方法,返回一个构造方法的数组,原因是一个类的构造方法可能是有多个。

如果只获取public的构造方法,则直接使用getConstructors即可。

通过getModifiers可以得到构造方法的类型,getParamterTypes可以得到构造方法的所有参数,返回一个Class数组。我们可以通过对getDeclaredConstructors的结果进行遍历,获得所有的构造方法的类型及对应的参数,示例代码如下:


TestClass test1 = new TestClass();
Class c = test1.getClass();
Constructor[] constructors1 = c.getDeclaredConstructors();
for(int i = 0;i<constructors1.length;i++){
System.out.print(Modifier.toString(constructors1[i].getModifiers())+"
参数:
");
Class[] params = constructors1[i].getParameterTypes();
for(int j = 0;j<params.length;j++){
System.out.print(params[j].getName()+"
");
}
System.out.println("");
}

输出结果:

public 参数:
private 参数: java.lang.String
public 参数: int java.lang.String
public 参数: int
2. 获取类的指定的构造方法
使用getDeclaredConstructor可以获得类的一个构造方法,其放回结果是一个Constructor对象,如果方法中不添加参数则获得的结果就是无参构造。
如果要获取有参构造,可以在getDeclaredConstructor方法中添加对应的参数。例如我们要获取有int和String的构造方法,代码如下:


try {
//无参构造
Constructor noParamsConstructor = c.getDeclaredConstructor();
//有int和String的构造
Class[] classes = {int.class,String.class};
Constructor intStringConstructor = c.getConstructor(classes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}

需要注意的是,由于有可能不存在对应的构造方法,所以需要用try-catch来包裹代码。

  1. 调用构造方法
    在使用反射获得类的构造方法之后,可以借用Constructor的newInstance方法得到类的实例:

     try {
    Class c1 = Class.forName("com.example.workdemo2.TestClass");
    Constructor noParamsConstructor1 = c1.getDeclaredConstructor();
    Object object = noParamsConstructor1.newInstance();
    Class[] classes1 = {int.class,String.class};
    Constructor intStringConstructor1 = c1.getConstructor(classes1);
    Object object1 = intStringConstructor1.newInstance(1,"111");
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (InstantiationException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }
    

如代码所示,如果是无参构造方法,可以直接使用Class的newInstance方法来获取类的实例.

  1. 获取和调用类的私有方法
    调用类的方法需要有类的实例对象,通过前面的构造方法我们获取到类的实例对象,然后就可以通过getDeclaredMethod方法获取到对应的方法,在通过invoke方法来执行类的方法。
    距离来说,我们为TestClass类添加一个私有方法:

    private void printData(String data) {
    System.out.println(“age:” + age + " name:" + name + " data:" + data);
    }
    然后我们获取这个私有方法并执行,代码如下:

    
    Class[] p4 = {String.class};
    Method method = c1.getDeclaredMethod("printData",p4);
    method.setAccessible(true);
    Object arg1s[] = {"testData"};
    method.invoke(object1,arg1s);
    

执行结果:

age:1 name:111 data:testData
5. 获取类的私有静态方法并执行
类中的静态方法也是可以通过反射获取到的,其执行方法和普通私有方法的获取相似,只是在最后执行时可以不去依靠具体的类实例。
我们先去添加一个静态方法:

private static void staticWork(){
System.out.println("static function");
}

反射代码:


Method method1 = c1.getDeclaredMethod("staticWork");
method1.setAccessible(true);
method1.invoke(null);

执行结果:

static function
6. 获取类的私有字段并修改值
反射获取类的字段是通过getDeclaredField方法来获取字段的,实例代码如下:


Field field = c1.getDeclaredField("name");
field.setAccessible(true);
field.set(object1,"changeData");

获取到Field对象之后,可以通过get方法获取变量内容,也可以通过set方法修改内容。
需要注意的是,如果使用set修改字段的话,仅仅是对当前的对象生效,对于其他的对象并没有修改效果。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

  1. 获取类的私有静态字段并修改
    和修改类的私有字段相同,修改私有静态字段也是需要通过getDeclaredField方法来实现。
    我们定义一个静态字段:

    private static String staticName = “default”;
    使用反射修改代码:

    
    Field field1 = c1.getDeclaredField("staticName");
    field1.setAccessible(true);
    field1.set(null,"changeStatic");
    

最后

以上就是拼搏纸飞机为你收集整理的【Java进阶营】Java反射复习的全部内容,希望文章能够帮你解决【Java进阶营】Java反射复习所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部