天天看点

java反射机制简述一,什么是反射二,反射常用方法三,总结

原文链接:https://www.cnblogs.com/fenjyang/p/11512045.html

一,什么是反射

1.1,反射:所谓框架的灵魂

​ 框架:半成品软件,可以在框架的基础上进行软件开发,简化代码。

​ 反射:将类的各个组成部分封装为其他对象,反射机制。

​ 简单来说反射就是在程序运行期间,动态的获取类或者对象中的属性。

​ 什么是动态获取。

​ 反射的原理就是通过类的字节码文件(class文件)反向获取该类或者对象中的属性,既然是通过字节码获取,这就需要JVM的操作了。下面请看API文档的说明:

java反射机制简述一,什么是反射二,反射常用方法三,总结

​ 在上图最后一句话中,文档说的很清楚,反射是在加载类时由JVM进行操作。

1.2,动静态编译

  • 静态编译:在编译期就确定类或者方法的属性,有点一次到位的意思。
  • 动态编译:在运行期确定类或者方法的属性,好比什么时候用就什么时候编译。

​ 但是这两种编译方式有什么区别,先说静态编译吧。我想大家都遇到过项目需求频繁变更的情况,可能是更改需求,可能是添加新的需求。对于静态编译,因为这是一次性编译,对于确定的代码是不能更改的,除非下线,更改,测试,再重新上线,显然这是不妥的。

​ 因此就需要动态编译,即在程序运行期间也可以进行相应的操作,一切操作方式都是灵活的,所以说反射对于程序是多么重要。

1.3,优缺点

​ 先来说说反射的优点:

​ 1,可以在程序运行的过程中,操作这些对象。

​ 2,可以解耦,提高程序的可扩展性。

​ 缺点:

​ 1,因为是JVM操作,所以对于性能来说会有所下降。

​ 2,容易对程序源码造成一定的混乱。

1.4,反射图解

java反射机制简述一,什么是反射二,反射常用方法三,总结

​ 注意:同一个字节码文件(*.class)在程序运行过程中,只会被加载一次。

1.5,反射获取方式

​ 获取Class对象的方式:

​ 1,Class.forName("全类名"):将字节码文件加载进内存,返回class对象

​ 多用于配置文件中,将类名定义在配置文件中,读取文件并加载类。

​ 2,类名.class:通过类名的属性class获取。

​ 多用于参数的构造。

​ 3,对象.getClass():该方法定义在Object中

​ 多用于对象的字节码获取。

public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // Class.forName("");
        Class c1 = Class.forName("com.api.reflect.User");
        System.out.println(c1);
        // 类名.class
        Class<User> c2 = User.class;
        System.out.println(c2);
        // .getClass
        User user = new User();
        Class c3 = user.getClass();
        System.out.println(c3);
            
System.out.println(c1 == c2);
    System.out.println(c1 == c3);
    System.out.println(c2 == c3);
}
           

}

​ 运行结果:

java反射机制简述一,什么是反射二,反射常用方法三,总结

​ 分析:

​ 通过以上三种反射方式都可以获得实例对象,同样也证明三个对象是相同的,也就是对象只会被创建一次。

二,反射常用方法

2.1,成员变量

  • public Field getField(String name)

    :获取指定名称的成员变量(public)。
  • public Field[] getFields()

    :获取全部成员变量(public)。
  • public Field getDeclaredField(String name)

    :不考虑修饰符。
  • public Field[] getDeclaredFields()

    :不考虑修饰符。

​ 创建一个User对象。

public class User implements Serializable {
            
<span class="hljs-keyword">public</span> String name;

<span class="hljs-keyword">protected</span> Integer age;

Integer sex;

<span class="hljs-keyword">private</span> String phone;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">()</span> </span>{
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(String name, Integer age, Integer sex, String phone)</span> </span>{
    <span class="hljs-keyword">this</span>.name = name;
    <span class="hljs-keyword">this</span>.age = age;
    <span class="hljs-keyword">this</span>.sex = sex;
    <span class="hljs-keyword">this</span>.phone = phone;
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">User</span><span class="hljs-params">(String name, Integer age)</span></span>{
    <span class="hljs-keyword">this</span>.name = name;
    <span class="hljs-keyword">this</span>.age = age;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{
    <span class="hljs-keyword">this</span>.name = name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> Integer <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> age;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(Integer age)</span> </span>{
    <span class="hljs-keyword">this</span>.age = age;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> Integer <span class="hljs-title">getSex</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> sex;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSex</span><span class="hljs-params">(Integer sex)</span> </span>{
    <span class="hljs-keyword">this</span>.sex = sex;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getPhone</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> phone;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPhone</span><span class="hljs-params">(String phone)</span> </span>{
    <span class="hljs-keyword">this</span>.phone = phone;
}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"User{"</span> +
            <span class="hljs-string">"name='"</span> + name + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">", age="</span> + age +
            <span class="hljs-string">", sex="</span> + sex +
            <span class="hljs-string">", phone='"</span> + phone + <span class="hljs-string">'\''</span> +
            <span class="hljs-string">'}'</span>;
}
 <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
    System.out.println(<span class="hljs-string">"跑步..."</span>);
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">eat</span><span class="hljs-params">(String username)</span> </span>{
    System.out.println(username + <span class="hljs-string">"正在吃饭..."</span>);
}
           

}

public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        // 1,通过Class.forName方式获取User对象
        Class aClass = Class.forName("com.api.reflect.User");
        // 获取public修饰的成员变量
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println("1,public修饰的成员变量--->" + field);
        }

        // 2,获取指定成员变量名称
        Field name = aClass.getField("name");
        System.out.println("2,指定成员变量名称--->" + name);

        // 3,获取全部的成员变量,忽略修饰符
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("3,不考虑修饰符,获取全部成员变量--->" + declaredField);
        }
        // 4,获取指定成员变量
        Field phone = aClass.getDeclaredField("phone");
        // 获取访问权限,暴力反射
        phone.setAccessible(true);
        System.out.println("4,暴力反射--->" + phone);
    }
}
           

​ 以上代码运行结果:

java反射机制简述一,什么是反射二,反射常用方法三,总结

2.2,构造方法

  • public Constructor<T> getConstructor(Class<?>... parameterTypes)

  • public Constructor<?>[] getConstructors()

  • public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

  • public Constructor<?>[] getDeclaredConstructors()

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        // 通过Class.forName方式获取User对象
        Class aClass = Class.forName("com.api.reflect.User");
        // 1,获取指定构造方法(public),参数是可变参数
        Constructor constructor = aClass.getConstructor(String.class, Integer.class, Integer.class, String.class);
        // 实例化对象
        Object user = constructor.newInstance("张三", , , "123456");
        System.out.println(user);
            
<span class="hljs-comment">// 2,获取全部构造方法(public)</span>
    Constructor[] constructors = aClass.getConstructors();
    <span class="hljs-keyword">for</span> (Constructor constructor1 : constructors) {
        System.out.println(constructor1);
    }

    <span class="hljs-comment">// 3,不考虑修饰符,获取指定构造方法</span>
    Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
    <span class="hljs-comment">// 获取权限</span>
    declaredConstructor.setAccessible(<span class="hljs-keyword">true</span>);
    Object declaredUser = declaredConstructor.newInstance(<span class="hljs-string">"李四"</span>, <span class="hljs-number">21</span>);
    System.out.println(<span class="hljs-string">"不考虑修饰符---&gt;"</span> + declaredUser);

    <span class="hljs-comment">// 4,获取全部构造方法</span>
    Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
    <span class="hljs-keyword">for</span> (Constructor declaredConstructor1 : declaredConstructors) {
        System.out.println(<span class="hljs-string">"不考虑修饰符---&gt;"</span> + declaredConstructor1);
    }
}
           

}

​ 以上代码运行结果:

java反射机制简述一,什么是反射二,反射常用方法三,总结

2.3,成员方法

  • public Method getMethod(String name,Class<?>... parameterTypes)

  • public Method[] getMethods()

  • public Method getDeclaredMethod(String name,Class<?>... parameterTypes)

  • public Method[] getDeclaredMethods()

public class ReflectMethod {
    public static void main(String[] args) throws Exception {
        // 通过Class.forName方式获取User对象
        Class aClass = Class.forName("com.api.reflect.User");
        // 1,获取指定成员方法,public修饰
        Method methodRun = aClass.getMethod("run");
        // 实例化User,并调用invoke()执行方法
        Object user = aClass.newInstance();
        methodRun.invoke(user);
        // 2,获取全部成员方法,public修饰
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        // 3,获取私有成员方法
        Method eat = aClass.getDeclaredMethod("eat", String.class);
        // 获取权限
        eat.setAccessible(true);
        // 执行方法
        eat.invoke(user,"小李");
    }
}
           

​ 执行结果为:

java反射机制简述一,什么是反射二,反射常用方法三,总结

​ 也许你有疑惑,哪里来这么多的方法。

​ 请详细看除了User对对象中的属性构造方法外,还有Object类中的方法。如下:

java反射机制简述一,什么是反射二,反射常用方法三,总结

这是为什么,请看API文档解释说明:

java反射机制简述一,什么是反射二,反射常用方法三,总结

包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口。

Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
           

java反射机制简述一,什么是反射二,反射常用方法三,总结

三,总结

​ 关于反射中的常用方法就总结到此,反射的用处还是很多的,比如Spring中IOC,DI都是利用反射机制实现的,当然这些会在另一篇博客中总结出来。

​ 以上内容均是自主总结,如有不适之处欢迎留言指正。

感谢阅读!

标签: 反射机制

<div id="blog_post_info">
           

好文要顶 关注我 收藏该文

java反射机制简述一,什么是反射二,反射常用方法三,总结
java反射机制简述一,什么是反射二,反射常用方法三,总结
java反射机制简述一,什么是反射二,反射常用方法三,总结

奋进的小样

关注 - 1

粉丝 - 10 +加关注 0 0

<div class="clear"></div>
<div id="post_next_prev">

<a href="https://www.cnblogs.com/fenjyang/p/11493015.html" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  class="p_n_p_prefix">« </a> 上一篇:    <a href="https://www.cnblogs.com/fenjyang/p/11493015.html" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  title="发布于 2019-09-09 17:33">Java之多线程(一)</a>
<br>
<a href="https://www.cnblogs.com/fenjyang/p/11520646.html" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  class="p_n_p_prefix">» </a> 下一篇:    <a href="https://www.cnblogs.com/fenjyang/p/11520646.html" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  title="发布于 2019-09-14 22:46">Spring之IOC</a>
           

posted @ 2019-09-12 15:15  奋进的小样  阅读( 343)  评论( 0)  编辑  收藏

</div>