本篇内容主要讲解“Java反射常见API的实例介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java反射常见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.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的实例介绍”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。