Java 反射

作者: 小石头呢 | 来源:发表于2019-09-14 13:20 被阅读0次

Java反射

  • Java反射API

  • 获取Class对象

  • 通过反射创建实例对象,调用公共方法

  • 通过反射调用私有方法

一.Java反射API

java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。即:通过class文件对象,去使用该文件中的成员变量、构造方法、成员方法。

1.java.lang.class类

java.lang.Class主要提供了以下两个功能:

  • 提供方法用于访问运行期间类的元数据;

  • 提供方法用于检查和修改类的运行时行为;

2.java.lang.class类常用方法

Method Des
public String getName() 返回类名
public static Class forName(String className)throws ClassNotFoundException 加载类并返回Class对象
public Object newInstance()throws InstantiationException,IllegalAccessException 创建实例对象
public boolean isInterface() 判断是否是接口
public boolean isArray() 判断是否是数组
public boolean isPrimitive() 判断是否是原始数据类型
public Class getSuperclass() 返回父类Class引用
Field getDeclaredField(String name) throws NoSuchMethodException,SecurityException 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields() throws SecurityException 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
Field getField(String name) throws SecurityException 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields() throws SecurityException 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Constructor<T> getDeclaredContructor(Class<?>... paramTypes) throws NoSuchMethodException,SecurityException 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Constructor<?>[] getDeclaredContructors() throws SecurityException 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
Constructor<T> getContructor(Class<?>... paramTypes) throws SecurityException 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor<?>[] getContructors() throws SecurityException 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法(不分什么修饰符修饰,都可以获取到)。
Method[] getDeclaredMethods() throws SecurityException 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method getMethod(String name, Class<?>... parameterTypes) throws SecurityException 返回一个 Method 对象,返回此 Class 对象所表示的类或接口的公共成员方法。
Method[] getMethods() throws SecurityException 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口的公共成员方法。

二.获取Class对象

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法。所以先要获取到每一个字节码文件对应的Class对应的Class类型的对象

1.Class类的静态方法forName(),根据全类名获取Class对象

  • 动态加载,运行时,开始装入类,并做类的静态初始化。

  • 知道类的全限定名时,可以使用该方式。注意原始数据类型不适用该方法。

public class GetClass {
   public static void main(String[] args) throws ClassNotFoundException {
       Class<?> c = Class.forName("swu.xl.day_18_self_Fanshe.GetClass");
       System.out.println(c.getName());
       System.out.println(c.getSimpleName());
   }
}

输出结果:
swu.xl.day_18_self_Fanshe.GetClass
GetClass

2.Object类的getClass()方法

  • 静态加载(编译时已加载)。

  • 从实例对象中获取Class对象。

public class GetClass {
   public static void main(String[] args) {
       GetClass g = new GetClass();
       Class<? extends GetClass> c = g.getClass();
       System.out.println(c.getName());
       System.out.println(c.getSimpleName());
   }
}

输出结果:
swu.xl.day_18_self_Fanshe.GetClass
GetClass

3.数据类型(基本和引用)的静态属性class

  • 静态加载(编译时已加载)

  • 作用于类名上,也可应用于原始数据类型。

public class GetClass {
   public static void main(String[] args) {
       Class<Boolean> c = boolean.class;
       System.out.println(c.getName());

       Class<GetClass> t = GetClass.class;
       System.out.println(t.getName());
   }
}

4.选择

一般,开发中使用第一种,因为第一种是一个字符串,而不是一个具体的类名。这样就可以把这样的字符串配置到配置文件中。

5.使用

Class类:常用类
成员变量:Field
构造方法: Constructor
成员方法:Method
反射:通过Class类的方法获取以上的三个对应的对象,然后通过Filed/Method/Contructor对象调用其方法去真正的使用类的成员、方法、构造

三.通过反射创建实例对象,调用公共方法

1.通过Class对象的newInstance()方法创建,这种方式只能调用无参构造方法

public class GetClass {
   public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
       //获得Class对象
       Class<?> c = Class.forName("swu.xl.day_18_self_Fanshe.Test");
       //创建实例对象
       Test o = (Test)c.newInstance();
       //调用方法
       o.message();
   }
}

public class Test {
   public void message(){
       System.out.println("test success");
   }
}

运行结果:
test success

2.通过Constructor对象的newInstance()方法创建,这种方式适用于有参构造方法,并且还可以破坏单例模式,调用私有构造方法

  • 注意这里可以根据传入参数的类型来得到指定的构造方法。还可以使用setAccessible修改访问权限。

  • <public void setAccessible(boolean flag) throws SecurityException将此对象的标志设置为true则表示反射的对象在使用时应该取消 Java 语言访问检查。

public class GetClass {
   public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
       //获得Class对象
       Class<?> c = Class.forName("swu.xl.day_18_self_Fanshe.Test");
       //得到反映此Class对象所表示的类或接口的指定构造方法
       Constructor<?> con = c.getDeclaredConstructor(String.class,Integer.class);
       //取消Java语言访问检查
       con.setAccessible(true);
       //创建实例对象
       Test o = (Test)con.newInstance(" message",5);
       //调用方法
       o.message();
   }
}

public class Test {

   //私有成员变量
   private String msg;
    private Integer num;

   //私有构造方法
   private Test(String msg,Integer num){
       this.msg = msg;
       this.num = num;
   }

   //方法
   public void message(){
       System.out.println("Get successful"+msg+" "+num+"条信息");
   }
}

运行结果:
Get successful message 5条信息

四.通过反射调用私有方法

  • 通过反射,我们可以调用其它类的私有方法,主要涉及java.lang.Class和java.lang.reflect.Method类。

  • 其中主要是用到了Method类的setAccessible方法和invoke方法,前者修改访问权限,后者调用方法。

public class GetClass {
   public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
       //获得Class对象
       Class<?> c = Class.forName("swu.xl.day_18_self_Fanshe.Test");
       //得到反映此Class对象中给定参数的构造方法
       Constructor<?> con = c.getDeclaredConstructor(String.class,Integer.class);
       //取消Java语言访问检查
       con.setAccessible(true);
       //创建实例对象
       Test o = (Test)con.newInstance("messages",5);
       //得到反映此Class对象中给定名字以及参数的方法
       Method message = c.getDeclaredMethod("message", new Class[]{int.class});
       //取消Java语言访问检查
       message.setAccessible(true);
       //调用私有方法
       message.invoke(o,5);
   }
}

public class Test {

   //私有成员变量
   private String msg;
   private Integer num;

   //私有构造方法
   private Test(String msg,Integer num){
       this.msg = msg;
       this.num = num;
   }

   //私有方法
   private void message(int count){
       System.out.println("Get " +num +" successful"+" "+msg+" "+count+"条信息没有收到");
   }
}

运行结果:
Get 5 successful messages 5条信息没有收到

参考文章:

相关文章

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射机制

    Java 反射机制 什么是反射 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 ...

  • 一探究竟:Java反射效率低的原因到底在哪?

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • 面试官说:大家都说 Java 反射效率低,你知道原因在哪里么

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • Java面试题之JavaSE高级

    一、Java中的反射 1.说说你对Java中反射的理解 java中的反射首先是能够获取到Java...

网友评论

    本文标题:Java 反射

    本文链接:https://www.haomeiwen.com/subject/ltrhectx.html