本篇内容主要讲解“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的实例介绍”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/1000241/blog/4612860