服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

新手入门:java中class类工作原理详解

1.class对象

class对象包含了与类相关的信息。事实上,class对象就是用来创建类的所有的“普通”对象的。

类是程序的一部分,每个类都有一个class对象。换言之,每当编写并且编译了一个新类,就会产生一个class对象(恰当地说,是被保存在一个同名的.class文件中)。在运行时,当我们想生成这个类的对象时,运行这个程序的java虚拟机(jvm)首先检查这个类的class对象是否已经加载。如果尚未加载,jvm就会根据类名查找.class文件,并将其载入。

一旦某个类的class对象被载入内存,它就被用来创建这个类的所有对象。看下面示例。

sweetshop.java

package com.zj.sample;
 
class candy {
    static {
       system.out.println("loading candy");
    }
}
 
class gum {
    static {
       system.out.println("loading gum");
    }
}
 
class cookie {
    static {
       system.out.println("loading cookie");
    }
}
 
public class sweetshop {
    public static void main(string[] args) {
       system.out.println("inside main");
       new candy();
       system.out.println("after creating candy");
       try {
           class.forname("com.zj.sample.gum");
       } catch (classnotfoundexception e) {
           system.out.println("couldn't find gum");
       }
       system.out.println("after class.forname(\"gum\")");
       new cookie();
       system.out.println("after creating cookie");
    }
}

结果:

inside main

loading candy

after creating candy

loading gum

after class.forname("gum")

loading cookie

after creating cookie

2.获取class实例的三种方式

1)利用对象调用getclass()方法获取该对象的class实例。

2)使用class类的静态方法forname(),用类的名字获取一个class实例。

3)运用.class的方式来获取class实例,对于基本数据类型的封装类,还可以采用.type来获取相对应的基本数据类型的class实例。

3.class.forname

上面的示例中:

class.forname("com.zj.sample.gum");

这个方法是class类(所有class对象都属于这个类)的一个static成员。class对象就和其它对象一样,我们可以获取并操作它的引用。forname()是取得class对象的引用的一种方法。它是用一个包含目标类的文本名的string作输入参数,返回的是一个class对象的引用。

4.类字面常量

java还提供了另一种方法来生成对class对象的引用,即使用“类字面常量”。对上述程序来说,可以是:

com.zj.sample.gum.class;

5.关键字instanceof

关键字instanceof返回一个布尔值,判断是不是某个特定类型的实例。

if(x instanceof dog) ((dog)x).bark();

6.获取class实例

package com.zj.sample;
 
class point {
    int x, y;
}
 
class classtest {
    public static void main(string[] args) {
       point pt = new point();
       class c1 = pt.getclass();
       system.out.println(c1.getname());
 
       try {
           class c2 = class.forname("com.zj.sample.point");
           system.out.println(c2.getname());
       } catch (exception e) {
           e.printstacktrace();
       }
 
       class c3 = point.class;
       system.out.println(c3.getname());
 
       class c4 = int.class;
       system.out.println(c4.getname());
 
       class c5 = integer.type;
       system.out.println(c5.getname());
 
       class c6 = integer.class;
       system.out.println(c6.getname());
    }
}

结果:

com.zj.sample.point

com.zj.sample.point

com.zj.sample.point

int

int

java.lang.integer

7.class的其他方法

1)class.newinstance()使用所选的class对象生成该类的新实例。它调用了缺省(无参数)的类构造器生成新的对象。所以使用newinstance()创建的类必须有一个缺省构造器。对于newinstance()来说,可以在原先没有任何对象存在的情况下,使用它创建一个新的对象。

利用newinstance()实例化一个对象:

package com.zj.sample;
 
class point {
    static {
       system.out.println("loading point");
    }
 
    int x, y;
}
 
class classtest {
    public static void main(string[] args) {
 
       try {
           class c = class.forname("com.zj.sample.point");
           point pt = (point) c.newinstance();
       } catch (exception e) {
           e.printstacktrace();
       }
 
    }
}

结果:

loading point

2)class.isinstance()方法提供了一种动态地调用instanceof运算符的途径。

3)class.getinterfaces()方法返回class对象的数组,这些对象代表的是某个class对象所包含的接口。

4)如果有一个class对象,那么就可以通过getsuperclass()获取它的直接基类。这个方法自然也是返回一个class引用,所以可以进一步查询其基类。这意味着在运行时,可以找到一个对象完整的类层次结构。

5)class类支持反射的概念,java附带的库java.lang.reflect包含了field、method以及constructor类(每个类都实现了member接口)。这些类型的对象是由jvm在运行时创建的,用以表示未知类里对应的成员。这样可以使用constructor创建新的对象,用get()和set()方法读取和修改与field对象关联的字段,用invoke()方法调用与method对象关联的方法。另外,还可以调用getfields()、getmethods、getconstrucotrs()方法,返回表示字段、方法以及构造器的对象的数组。

8.利用反射api察看未知类的构造方法与方法

package com.zj.sample;
 
import java.lang.reflect.constructor;
import java.lang.reflect.method;
 
class point {
    static {
       system.out.println("loading point");
    }
 
    int x, y;
 
    void output() {
       system.out.println("x=" + x + "," + "y=" + y);
    }
 
    point(int x, int y) {
       this.x = x;
       this.y = y;
    }
}
 
class classtest {
    public static void main(string[] args) {
       
       try {
           class c = class.forname("com.zj.sample.point");
           constructor[] cons = c.getdeclaredconstructors();
           for (int i = 0; i < cons.length; i++)// 返回所有声明的构造方法
           {
              system.out.println(cons[i]);
           }
           method[] ms = c.getdeclaredmethods();
           for (int i = 0; i < ms.length; i++)// 返回所有声明的方法
           {
              system.out.println(ms[i]);
           }
 
       } catch (exception e) {
           e.printstacktrace();
       }
    }
}

结果:

loading point

com.zj.sample.point(int,int)

void com.zj.sample.point.output()

9.动态调用一个类的实例(完全没有出现point这个名字)

package com.zj.sample;
 
import java.lang.reflect.constructor;
import java.lang.reflect.method;
 
class point {
    static {
       system.out.println("loading point");
    }
 
    int x, y;
 
    void output() {
       system.out.println("x=" + x + "," + "y=" + y);
    }
 
    point(int x, int y) {
       this.x = x;
       this.y = y;
    }
}
 
class classtest {
    public static void main(string[] args) {
       
       try {
           class c = class.forname("com.zj.sample.point");
           constructor[] cons = c.getdeclaredconstructors();
           class[] params = cons[0].getparametertypes();// 察看构造器的参数信息
           object[] paramvalues = new object[params.length];// 构建数组传递参数
           for (int i = 0; i < params.length; i++) {
              if (params[i].isprimitive())// 判断class对象表示是否是基本数据类型
              {
                  paramvalues[i] = new integer(i);
              }
           }
           object o = cons[0].newinstance(paramvalues);// 创建一个对象的实例
           method[] ms = c.getdeclaredmethods();// 调用方法
           ms[0].invoke(o, null);// 用指定的参数调用(output方法没有参数,null)
       } catch (exception e) {
           e.printstacktrace();
       }
  }
}

结果:

loading point

x=0,y=1

扫描关注微信公众号