黑马程序员技术交流社区

标题: 关于反射的一个问题 [打印本页]

作者: 白堇翎    时间: 2013-8-6 21:24
标题: 关于反射的一个问题
本帖最后由 白堇翎 于 2013-8-6 23:21 编辑

构造代码块和静态代码块,可以反射吗?

作者: 黑马李昂    时间: 2013-8-6 23:00
  1. package heima;

  2. public class Demo {

  3. public static void main(String[] args) {

  4. TestOne one = null;

  5. try {
  6. Class cla = Class.forName("heima.TestOne");// 进行heima.TestOne类加载,返回一个Class对象
  7. System.out.println("********");
  8. one = (TestOne) cla.newInstance();// 产生这个Class类对象的一个实例,调用该类无参的构造方法,作用等同于new TestOne()
  9. } catch (Exception e) {
  10. e.printStackTrace();
  11. }
  12. TestOne two = new TestOne();

  13. System.out.println(one.getClass() == two.getClass());// 比较两个TestOne对象的Class对象是否是同一个对象,在这里结果是true。说明如果两个对象的类型相同,那么它们会有相同的Class对象
  14. }
  15. }

  16. class TestOne {

  17. static {
  18. System.out.println("静态代码块运行");
  19. }

  20. TestOne() {
  21. System.out.println("构造方法");
  22. }
  23. }
复制代码


代码分析:


       在进行Class.forName("com.TestOne")的时候,实际上是对heima.TestOne进行类加载,这时候,会把静态属性、方法以及静态代码块都加载到内存中。所以这时候会打印出"静态代码块运行"。但这时候,对象却还没有产生。所以"构造方法"这几个字不会打印。当执行cla.newInstance()的时候,就是利用反射机制将Class对象生成一个该类的一个实例。这时候对象就产生了。所以打印"构造方法"。当执行到TestOnetwo=new TestOne()语句时,又生成了一个对象。但这时候类已经加载完毕,静态的东西已经加载到内存中,而静态代码块只执行一次,所以不用再去加载类,所以只会打印"构造方法",而"静态代码块运行"不会打印。

  1. package heima;

  2. import java.lang.reflect.Constructor;

  3. /**
  4. *本类测试反射获得类的构造器对象,
  5. *并通过类构造器对象生成该类的实例
  6. */

  7. public class Demo1 {

  8. public static void main(String[] args) {

  9. try {
  10. //获得指定字符串类对象
  11. Class cla=Class.forName("heima.Tests");
  12. //设置Class对象数组,用于指定构造方法类型
  13. Class[]cl=new Class[]{int.class,int.class};
  14. //获得Constructor构造器对象。并指定构造方法类型
  15. Constructor con=cla.getConstructor(cl);
  16. //给传入参数赋初值
  17. Object[]x={new Integer(1),new Integer(2)};
  18. //得到实例
  19. Object obj = con.newInstance(x);
  20. } catch(Exception e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }

  25. class Tests{
  26. public Tests(int x,int y){
  27. System.out.println(x+"....."+y);
  28. }
  29. }
复制代码


说明我们已经生成了Tests这个类的一个对象。

        对于反射这部分内容理解的不是很好,结合网上某大神,试着分析你的疑问,写的不对的地方多多不吝赐教!

        还有祝陈兄进入黑马的关键冲刺阶段顺利!{:soso_e100:} 静待佳音

作者: 哪颗最亮的星星    时间: 2013-8-6 23:11
首先要明确的是静态代码块和构造代码块的作用,它们分别是给类进行初始化以及给所有对象进行初始化 。哪么当我用到反射时的时候,也就是说,当Class.forName("className");时,其实已经执行了静态代码块,当通过
Constructor   cons=clazz.getConstrutor();
类名  变量名=cons.newInstance(); 这时,已经执行了构造代码块

        public static void main(String [] args) throws Exception
        {
                Class<?> clazz=Class.forName("cn.itcast.Test1");

                Constructor cons=clazz.getConstructor(String.class);

                Test1 t=(Test1)cons.newInstance("wangwu");
                Test1 t2=(Test1)cons.newInstance("zhaoliu");
               

        }









package cn.itcast;

public class Test1
{

        /**
         * @param args
         */
        private String name;
        static
        {
                System.out.println("static code");
        }
        {
                System.out.println("Constructor code");
        }

        public Test1(String name)
        {
                this.name=name;
        }

        public String getName()
        {
                return name;
        }
}


作者: 白堇翎    时间: 2013-8-6 23:17
黑马李昂 发表于 2013-8-6 23:00
代码分析:

       在进行Class.forName("com.TestOne")的时候,实际上是对heima.TestOne进行类加载,这 ...

首先感谢回答
另外大概这也是反射构造代码块和静态代码块的一种方式吧,得到这个类的字节码,并不创建实例.

我原本的想法是既然方法可以用Method反射,成员变量可以用Field反射,那么有没有一种方法可以反射构造代码块,静态代码块.
根本就没有想到构造代码块,静态代码块在类被加载的时候就被执行这里去.
你倒是提醒了我这一点,单看你的代码,应该在第十行的时候调用的TestOne的静态代码块.
然后...顿时觉得根本不可能有一种方法专门用来反射代码块...因为代码块都是在类被加载的时候就执行了的东西..而反射的前提就是获得字节码,把类加载进内存..
茅塞顿开...

作者: 白堇翎    时间: 2013-8-6 23:20
哪颗最亮的星星 发表于 2013-8-6 23:11
首先要明确的是静态代码块和构造代码块的作用,它们分别是给类进行初始化以及给所有对象进行初始化 。哪么 ...

如果要反射构造代码块,那么就要反射构造函数..
这一点 也学习了 感谢回答




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2