A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 唐长智 中级黑马   /  2013-2-28 13:34  /  1963 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

看到张老师的视频中用暴力反射得到了类中私有的成员,那么能不能通过暴力反射得到单例中的私有的构造函数,暴力的再创建新的对象呢?

评分

参与人数 1技术分 +1 收起 理由
高境 + 1 赞一个!

查看全部评分

3 个回复

正序浏览
王文正 发表于 2013-2-28 13:48
我来回答你的问题 是可以通过暴力反射得到单例中的私有的构造函数 我给你举一个我自己运行出的一个例子,希 ...

喔,最后这两句话好屌,不懂觉厉
回复 使用道具 举报
???? 我怎么得出不同的结果

  1. import java.lang.reflect.Method;
  2. import java.lang.reflect.Constructor;

  3. class Test24
  4. {
  5.         public static void main(String[] args)throws Exception
  6.         {
  7.                
  8.                 Constructor[] cs = PvClas.class.getDeclaredConstructors();      //得到构造函数数组,这里只有一个
  9.                 //System.out.println(cs);                          //输出[Ljava.lang.reflect.Constructor;@64883c
  10.                 //System.out.println(cs[0]);                        //输出private PvClas(int)
  11.         cs[0].setAccessible(true);
  12.                 PvClas pc = (PvClas)cs[0].newInstance(3);          // 用这个构造函数建一个对象,并传入参数。
  13.                
  14.                 System.out.println(pc.getX());                     //输出为3
  15.                

  16.         }
  17. }


  18. class PvClas
  19. {
  20.         private int x = 7;
  21.        
  22.         private PvClas(int x)
  23.         {
  24.                 this.x = x;
  25.         System.out.println("私有构造函数");

  26.         }

  27.         public int getX()
  28.         {
  29.                 return x;
  30.         }
  31. }
复制代码
//上面的PvClas类 只有一个私有构造函数和提供访问私有变量X的getX()方法。
//Test24通过通过暴力反射用构造函数建立个对象,把私有成员的值改变了。
回复 使用道具 举报
我来回答你的问题 是可以通过暴力反射得到单例中的私有的构造函数 我给你举一个我自己运行出的一个例子,希望对你有用!
代码如下:
 package study.spring.bean;
  public class SimpleBean
  {
  private String beanName;
  private SimpleBean() {
  System.out.println( " SimpleBean " );
  }
  /** */ /**
  * @return Returns the beanName.
  */
  public String getBeanName()
  {
  return beanName;
  }
  /** */ /**
  * @param beanName The beanName to set.
  */
  public void setBeanName(String beanName)
  {
  this .beanName = beanName;
  }
  }
  发现能调用成功,但不能构造只有私有构造函数的类。

然后你再看看这个里例子:
  package study.spring.bean;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.InvocationTargetException;
  public class SimpleTest
  {
  /** *//**
  * @param args
  */
  public static void main(String[] args)
  {
  // TODO Auto-generated method stub
  try
  {
  Constructor[] cts=Class.forName("study.spring.bean.SimpleBean").getDeclaredConstructors();
  for(int i=0;i<cts.length;i++){
  cts.newInstance(null);
  }
  }
  catch (SecurityException e)
  {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  catch (ClassNotFoundException e)
  {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  catch (IllegalArgumentException e)
  {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  catch (InstantiationException e)
  {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  catch (IllegalAccessException e)
  {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  catch (InvocationTargetException e)
  {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  }
  }

相比较一下你会得出:
实际上java在反射创建一个类的实例时,默认会检测是否符合相关安全,该检测开关可以关闭。
Constructor、Field、Method都是继承于AccessibleObject,对应实例调用setAccessible(true)就关闭该开关
如上面的例子,在代码 cts
.newInstance(null);行前调用上述方法: cts.setAccessible(true);
这样就可以创建只有构造函数的实例、调用私有构造方法,访问类的私有属性。
这样好像java安全性就大大降低.如果你非常注重应用的安全性,java当然考虑到这方面,
你可以在JVM启动参数增加 -Djava.security.manager 启用安全管理器,
如果有该参数,它将检测正在关闭接入检测的代码是否许可了这样做,上述代码执行时会抛出java.security!

评分

参与人数 1技术分 +1 收起 理由
高境 + 1 赞一个!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马