Java通过反射可以设置私有变量的好处有哪
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java通过反射可以设置私有变量的好处有哪相关的知识,希望对你有一定的参考价值。
Java通过反射可以设置私有变量的好处有public class PrivateTest private String name = "hello"; public String getName() return name; public class ReflectionTest public static void main(String[] args) throws Exception PrivateTest pt = new PrivateTest(); Class clazz = PrivateTest.class; Field field = clazz.getDeclaredField("name"); field.setAccessible(true); field.set(pt, "world"); field.setAccessible(false); System.out.println(pt.getName()); 这样通过反射可以设置私有变量,Java当时设计的时候是出于什么考虑的呢?
但是也有应用的场景,可以想到的是: hibernate中你定义实体类及相应的字段(和数据库表对应),你可以在映射文件中配置: 当你从数据库中获取到数据后,是调用类的setxxx()方法,还是直接给字段赋值,这里字段是可以设置成private的,用的就是反射。那java反射可以设置私有变量的值,是好处多还是坏处多呢? 问题补充:robertliudeqiang 写道提供了一种接口吧,一般情况下不会用的。
但是也有应用的场景,可以想到的是: hibernate中你定义实体类及相应的字段(和数据库表对应),你可以在映射文件中配置: 当你从数据库中获取到数据后,是调用类的setxxx()方法,还是直接给字段赋值,这里字段是可以设置成private的,用的就是反射。目前反射设置private变量的值,还未看出是有好处 的。
那应该是java的一个问题遗留,为了兼容没法解决的。 参考技术A 利用反射能 //假设类名为A// 实例化类A p = new A();// 获取classClass c = p.getClass();// 获取该类所有的字段Field[] fields = c.getDeclaredFields();// 遍历赋值for (int i = 0; i < fields.length; i++) String filedName = fields[i].ge.
反射那些事
一直以为只要把类的成员变量设置为private,或者方法设置为private,那么他就对外完全隐藏,类外部无法直接对该成员变量或者方法进行直接访问。但是java的反射,拥有十分强大的功能,它可以访问类中的任意成员变量和方法,我们可以通过反射直接入侵类的私有变量和私有方法,私有构造器。我们来了解一下反射的一些用法吧。
package com.reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
class Person{
public final Integer id=1001;
private String name;
public Person() {}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
private void say(String message){
System.out.println("You want to say: "+message);
}
}
public class Reflect {
@Test
public void testGetField() throws ClassNotFoundException {
Class<?> clazz=Class.forName("com.reflect.Person");
//获得声明为public域的字段
System.out.println("Fields: "+Arrays.toString(clazz.getFields()));
//获取所有的字段
System.out.println("Declared Fields: "+Arrays.toString(clazz.getDeclaredFields()));
}
//通过类型标签我们只能调用无参的构造器
//以下是如果通过反射调用带参数的构造器
@Test
public void test() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> clazz=Class.forName( "com.reflect.Person" );
Constructor c=clazz.getConstructor(String.class);
Person person= (Person) c.newInstance("viscu");
System.out.println(person.getName());
}
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
Person person=new Person();
Class<?> classType=person.getClass();
//访问私有方法
//getDeclaredMethod可以获取到所有方法,而getMethod只能获取public
Method method=classType.getDeclaredMethod("say", String.class);
//设置为true 可以忽略对类相关访问权限的检查
method.setAccessible(true);
//通过反射调用person类中的private方法
method.invoke(person,"check");
//入侵类内部的私有成员变量
Field field=classType.getDeclaredField("name");
field.setAccessible(true);
field.set(person,"walk");
System.out.println(person.getName());
}
}
以上就是通过反射对类的私有域进行访问的一些例子,利用反射我们可以轻易地入侵到类的内部,举个通过入侵改变类的运行机制的例子。
单例模式(顾名思义:就是该类型的类只有一个实例)
public class SingletonTest {
private static final SingletonTest INSTANCE = new SingletonTest();
private SingletonTest(){
//todo
}
public static SingletonTest getInstance(){
return INSTANCE;
}
public void show(){
System.out.println("Singleton using static initialization in Java");
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
SingletonTest demo=SingletonTest.getInstance();
demo.show();
Class<?> clazz=SingletonTest.class;
SingletonTest o= (SingletonTest) clazz.newInstance();
o.show();
System.out.println(demo==o);
}
}
虽然我们把Singleton的构造器设置为private了,可是我们还是可以通过反射轻易地构造出第二个SingletonTest 实例,第三个,第四个.....等,那么就违背了单例模式的本意了。
至于如何预防
- 我们可以在私有构造器中抛出一个异常即可防止构建新的实例。
private SingletonTest(){
if(INSTANCE!=null){
throw new RuntimeException("you can‘t create another one");
}
}
反射,让我们原本以为安全的类变得不那么安全了,别人可以轻易入侵你的类内部改变你的原有数据,至于如何预防,有待研究。
以上是关于Java通过反射可以设置私有变量的好处有哪的主要内容,如果未能解决你的问题,请参考以下文章