黑马程序员技术交流社区

标题: 反射加载问题 [打印本页]

作者: 罗磊    时间: 2012-8-5 12:02
标题: 反射加载问题
Class clazz = Class.forName("cn.heima.reflect.person");
Class clazz = new person().getClass();
Class clazz = person.class;
上面的三条语句都是加载类的 那选那一句最好 我想是第三句 但见老师多写第一句 所以有点蒙
还有这三句话在内存中是如何存在的
请帮忙解释下 要是有内存图就更好啊

作者: 郑文博    时间: 2012-8-5 14:50
三者是一样的,没好坏之分,都是针对个例程序时选择更为适合的方法。
都是获取类的字节码文件。通俗理解就是程序运行后生成的*.class文件。但实质上*.class文件并不是真正的字节码文件,*.class是有特殊编码的文件,你用Class.forName("cn.heima.reflect.person");new person().getClass();person.class;三种方法获取时*.class文件会由二进制重新编码生成才是真正的字节码文件。
所以*.class是存在硬盘的不在内存,你选择的三种方法加载都是存在于内存的方法区的。
作者: 黑马振鹏    时间: 2012-8-5 15:06
Class clazz = Class.forName("cn.heima.reflect.person");
有两种返回方式:
(1)如果字节码已经存在可以直接返回
(2)如果字节码还没有加载,先让类加载器加载,然后再返回。
这种将会是以后实际开发中最常用的方式。
作者: 余明辉    时间: 2012-8-5 20:06
对,第一句是最好的。
第一句这个方法是按参数中指定的字符串形式的类名去搜索并加载相应的类,如果该类已经被加载过,则返回代表该Class的实例对象,否则,按类加载器的委托机制去搜索和加载该类,如果所有的类加载器都无法加载到该类,则抛出ClassNotFoundException。加载完这个Class字节码后,接着就可以使用Class字节码的newInstance方法去创建该类的实例对象了。
有时候,我们程序中所有使用的具体类名在设计时(即开发时)无法确定,只有程序运行时才能确定,这时候就需要使用Class.forName去动态加载该类,这个类名通常是在配置文件中配置的,框架的设计原理就是建立反射基础上的

下面是模拟的一个小框架例子,希望可以帮助你理解
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;

public class Demo {
        public static void main(String[] args) throws Exception {
               

                //加载一个properties文件
                InputStream fis = Demo.class.getResourceAsStream("config.properties");
               
                Properties prop = new Properties();
                prop.load(fis);
                fis.close();               
                String className = prop.getProperty("className");        //通过Key,拿到相对应的value

                //通过反射,拿到的是这个配置文件中的className的实例
                Collection collection = (Collection)Class.forName(className).newInstance();               


                ReflectPoint p1 = new ReflectPoint(3,3);
                ReflectPoint p2 = new ReflectPoint(5,5);
                ReflectPoint p3 = new ReflectPoint(3,3);
               
                collection.add(p1);
                collection.add(p2);
                collection.add(p3);

                System.out.println(collection.size());
        }
}

作者: hello world    时间: 2012-8-5 22:07
Class clazz = Class.forName("cn.heima.reflect.person");这种方式是看内存中是否有Person类,没有就将Person类加载进内存。
Class clazz = new person().getClass();这种方式就是通过类的实例调用父类(Object)中的getClass()来获取Class的实例,因为一个类的所有实例都对应内存中的一份字节码。
Class clazz = person.class这种方式就是直接通过类名.class的方式放回Class的实例了。.class应该算是类的属性。
其实三种方式没有好坏,具体情况具体分析,选哪种其实没多大的区别。


作者: 罗磊    时间: 2012-8-6 09:32
问题解决啊  谢谢




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