**重点内容**## Class类 究竟怎么用 ##
首先说一点 Class类究竟是什么?概括来讲Class类是描述类的类。我们都知道,java程序其实
是由一个个对象组成,他们属于什么类,继承自什么类,这一系列的信息都是Class类来描述的。类是 描述对象的 ,那类怎么描述呢 Class类。假设A a=new A();a对象的空间中其实有一个指针指向它的Class对象,程序中怎么获取呢?a.getClass().
package learnTest;
/*
* 我们知道 Java世界是运行在虚拟机之上的,我们的代码 经过编译器 变异之后 生成的是.class 文件。运行期间,我们实例化任何一个类时,jvm 首先会在内存中
* 找有无这个类,若不存在,将这个类加载到内存中,当加载这个类或者是类加载器的define class方法 被调用时,便会为这个类产生一个Class对象,或者说,这
* 个类的Class对象生成,来标识这个类。所有的由该类产生的实例都共同拥有着这个Class对象。若存在,直接创建实例。一般某个类的Class对象被载入内存,它
* 就用来创建这个类的所有对象。注意.class文件并不是所有的都会被加载到内存,只有在需要的时候才会进行加载。
* Class类没有公有的构造方法,那么他是怎么被"创造"出来的呢?
* 答:在new 一个 对象时或者加载类加载器时 由jvm自动调用。
* 怎么得到Class对象呢?
* 答:1.Class.forName("类的全限定名",boolean initlize,classloader);
* 2.Person p=new Person();p.getClass();
* 3.Person.class;
* Class类有什么使用技巧?
* 1.s lalala=Class.forName(s).newInstance();//s 类的全限定名
* 利用上面代码可以根据存储在s中的类名创建对象。
* 2 虚拟机为每一类(型)管理一个独一无二的Class对象。可以用==比较 类对象。
*
* 一定要明白的:
* 1. forName这句话就是装载类用的(new是根据加载到内存中的类创建一个实例,要分清楚)。
* 2. 至于什么时候用,可以考虑一下这个问题,给你一个字符串变量,它代表一个类的包名和类名,你怎么实例化它?
* A a = (A)Class.forName("pacage.A").newInstance();这和 A a =new A();是一样的效果。
* 3. jvm在装载类时会执行类的静态代码段,要记住静态代码是和class绑定的,class装载成功就表示执行了你的静态代码了,而且以后不会
* 再执行这段静态代码了。
* 4. Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段。
* 5. 动态加载和创建Class 对象,比如想根据用户输入的字符串来创建对象
* String str = 用户输入的字符串
* Class t = Class.forName(str);
* t.newInstance();
*
*
*
* */
/*二.在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?
1.它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。
2.那么为什么会有两种创建对象方式?
这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。
Java中工厂模式经常使用newInstance()方法来创建对象,因此从为什么要使用工厂模式上可以找到具体答案。例如:
class c = Class.forName(“Example”);
factory = (ExampleInterface)c.newInstance();
其中ExampleInterface是Example的接口,可以写成如下形式:
String className = "Example";
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
进一步可以写成如下形式:
String className = readfromXMlConfig;//从xml 配置文件中获得字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
上面代码已经不存在Example的类名称,它的优点是,无论Example类怎么变化,上述代码不变,甚至可以更换Example的兄弟类Example2 , Example3 , Example4……,只要他们继承ExampleInterface就可以。
3.从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。 但是使用newInstance()方法的时候,
就必须保证:
1、这个类已经加载;
2、这个类已经连接了。
而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载 Java API的那个加载器。
现在可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好
的灵活性,提供给了一种降耦的手段。
三.最后用最简单的描述来区分new关键字和newInstance()方法的区别:
1. newInstance: 弱类型。低效率。只能调用无参构造。
2. new: 强类型。相对高效。能调用任何public构造。
*/
public class ClassLoader_learn {
static {
Person person;
System.out.println("ClassLoader_learn class loaded!");
}
public static void main(String[] args) {
Class testClassForName = null,testPointGetclass,testPointclass,testObject;
testPointclass=Person.class;
System.out.println("类名.class-----------"+testPointclass);
try {
testClassForName=Class.forName("learnTest.Person");
System.out.println("Class.forName------"+testClassForName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person p=new Person();
testPointGetclass=p.getClass();
System.out.println("实例对象.getClass---------"+testPointGetclass);
//创建一个 Person 对象
Person p2=new Person();
testObject= p2.getClass();
if(testClassForName==testPointclass&&testClassForName==testPointGetclass&&testObject==testClassForName){
System.out.println("equal!");
}
}
}
gg