Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6895236
  • 博文数量: 3857
  • 博客积分: 6409
  • 博客等级: 准将
  • 技术积分: 15948
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-02 16:48
个人简介

迷彩 潜伏 隐蔽 伪装

文章分类

全部博文(3857)

文章存档

2017年(5)

2016年(63)

2015年(927)

2014年(677)

2013年(807)

2012年(1241)

2011年(67)

2010年(7)

2009年(36)

2008年(28)

分类:

2012-04-15 21:22:42

原文地址:Java中Class类工作原理详解 作者:daizhe

  1.Class对象

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

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

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

  SweetShop.java

双击代码全选

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

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实例

双击代码全选

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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()实例化一个对象:

双击代码全选

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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察看未知类的构造方法与方法

双击代码全选

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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这个名字)

双击代码全选

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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

阅读(339) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~