温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java反射常见API的实例介绍

发布时间:2021-07-28 17:16:02 来源:亿速云 阅读:179 作者:chen 栏目:大数据

本篇内容主要讲解“Java反射常见API的实例介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java反射常见API的实例介绍”吧!

什么是反射

Java反射常见API的实例介绍

反射常用API

通过反射和自定义注解获取属性信息

static void initUser(User user) throws IllegalAccessException {

  // 获取User类中所有的属性(getFields无法获得private属性)
  Field[] fields = User.class.getDeclaredFields();

  // 遍历所有属性
  for (Field field : fields) {
    // 如果属性上有此注解,则进行赋值操作
    if (field.isAnnotationPresent(InitSex.class)) {
      InitSex init = field.getAnnotation(InitSex.class);
      field.setAccessible(true);
      // 设置属性的性别值
      field.set(user, init.sex().toString());
      System.out.println("完成属性值的修改,修改值为:" + init.sex().toString());
    }
  }
}

获取Class对象的三种方法

第一种方法:当你知道类的全路径名时,可使用Class.forName静态方法来获得Class对象。上面的示例就是通过这种方法获得:

Class clz = Class.forName("com.choupangxia.reflect.User");

第二种方法:通过“.class”获得。前提条件是在编译前就能够拿到对应的类。

Class clz = User.class;

第三种:使用类对象的getClass()方法。

User user = new User();
Class clz = user.getClass();

创建对象的两种方法

可以通过Class对象的newInstance()方法和通过Constructor 对象的newInstance()方法创建类的实例对象。

第一种:通过Class对象的newInstance()方法。

Class clz = User.class;
User user = (User) clz.newInstance();

第二种:通过Constructor对象的newInstance()方法。

Class clz = Class.forName("com.xxx.reflect.User");
Constructor constructor = clz.getConstructor();
User user = (User) constructor.newInstance();

其中第二种方法创建类对象可以选择特定构造方法,而通过 Class对象则只能使用默认的无参数构造方法。

Class clz = User.class;
Constructor constructor = clz.getConstructor(String.class);
User user = (User) constructor.newInstance("公众号");

获取类属性、方法、构造器

通过Class对象的getFields()方法获取非私有属性。

Field[] fields = clz.getFields();
for(Field field : fields){
  System.out.println(field.getName());
}

上述实例中的User对象属性都是private,无法直接通过上述方法获取,可将其中一个属性改为public,即可获取。

通过Class对象的getDeclaredFields()方法获取所有属性。

Field[] fields = clz.getDeclaredFields();
for(Field field : fields){
  System.out.println(field.getName());
}

执行打印结果:

username
age

当然针对属性的其他值也是可以获取的,针对私有属性的修改需要先调用field.setAccessible(true)方法,然后再进行赋值。关于具体应用,回头看我们最开始关于注解的实例中的使用。

获取方法的示例如下:

Method[] methods = clz.getMethods();
for(Method method : methods){
  System.out.println(method.getName());
}

打印结果:

setUsername
setAge
getUsername
getAge
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

可以看到,不仅获取到了当前类的方法,还获取到了该类父类Object类中定义的方法。

关于获取构造器的方法上面已经讲到了,就不再赘述。而上述的这些方法在Class中都有相应的重载的方法,可根据具体情况进行灵活使用。

利用反射创建数组

最后,我们再看一个通过反射创建数组的实例。

@Test
public void createArray() throws ClassNotFoundException {
  Class<?> cls = Class.forName("java.lang.String");
  Object array = Array.newInstance(cls,5);
  // 向数组添加内容
  Array.set(array,0,"Hello");
  Array.set(array,1,"公众号");
  Array.set(array,2,"Java");
  // 获取数组中指定位置的内容
  System.out.println(Array.get(array,2));
}

一个例子

public class User {
   static String country;
   private String name;
   public int age;
   private Result<String> result;
   public void say(String world){
       System.out.println("我说:" + world);
  }
   private void writeNote(){
       System.out.println("写日记");
  }
   public String getName() {
       return name;
  }
   public void setName(String name) {
       this.name = name;
  }
   public Result<String> getResult() {
       return result;
  }
   public void setResult(Result<String> result) {
       this.result = result;
  }
   @Override
   public String toString() {
       return "User{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
  }
}
public class ReflectTest {
   public static void main(String[] args) throws Exception{
       reflectDemo();
  }
   public static void reflectDemo() throws Exception{
       Class clazz = Class.forName("kite.lab.reflect.User");
       Field[] declaredFields = clazz.getDeclaredFields();
       for(Field declaredField:declaredFields){
           System.out.println(declaredField.getName());
      }
       Method[] methods = clazz.getDeclaredMethods();
       for(Method method:methods){
           System.out.println(method.getName());
      }
       Object userInstance = clazz.newInstance();
       Method sayMethod = clazz.getDeclaredMethod("say", String.class);
       sayMethod.invoke(userInstance,"你好");
       Method writeNoteMethod = clazz.getDeclaredMethod("writeNote");
       writeNoteMethod.setAccessible(true);
       writeNoteMethod.invoke(userInstance);
  }
}

总结

说起反射,大家可能都知道性能差。那反射的性能为什么差呢?

根本的原因就是因为反射是动态加载,所以 jit 对其所做的优化极其有限。

jit - 即时编译器,是 JVM 优化性能的杀手级利器,它会对热点代码进行一系列优化,比如非常重要的优化手段-方法内联。而反射的代码则享受不到这种待遇。

反射中性能最差的部分在于获取方法和属性的部分,比如 getMethod() 方法,是因为获取这个方法需要遍历所有的方法列表,包括父类。而如果不是反射的话,那这个方法地址都是提前确定的。


到此,相信大家对“Java反射常见API的实例介绍”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI