Class和 forName(String className)的作用

在Java语言当中,有一个java.lang.Class类,这个类有点“特殊”。不可否认,java.lang.Class类是一种类型;但是,java.lang.Class类与普通类(例如Integer、String等)是不同的。

在本文当中,对java.lang.Class类的讨论分为4个部分:前2个部分是讲java.lang.Class与普通类的区别,第3个部分是如何获取java.lang.Class类的对象和简单的使用,第4部分是对于java.lang.Class类的forClass方法进行一个小小的深入讨论。

1、java.lang.Class类的创建者

java.lang.Class类的创建者是“Java Virtual Machine(JVM)”,而普通类(例如Integer、String等)的创建者是“程序开发人员”。

普通类是由程序开发人员使用的,以String类为例,代码如下:

public static void main(String[] args)
{
	String str = new String("Hello World");
	System.out.println(str.length());
}

而java.lang.Class类的创建则是由JVM来完成的,对于java.lang.Class的描述中有一段是这样的:

Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.

由上面这段描述可知,java.lang.Class类是没有公共构造函数的(Class has no public constructor),它由JVM调用(Class objects are constructed automatically by the Java Virtual Machine)。下面是java.lang.Class类的构造函数的源代码:

    /*
     * Constructor. Only the Java Virtual Machine creates Class
     * objects.
     */
    private Class() {}

值得注意的是:java.lang.Class的实例,虽然由JVM来创建,但是并不代表“该实例只能由JVM使用”。换句话说,由JVM创建java.lang.Class实例,接下来程序开发人员对该实例进行使用

在本小节当中,主要是讲java.lang.Class的实例是由JVM创建的,与其它普通类(例如Integer、String是由程序开发人员创建的)不同,在明白了这样一个前提下,我们接下来看一看java.lang.Class到底有什么特别的作用。

2、java.lang.Class类的作用

不可否认,java.lang.Class类是一种数据类型(Type)。

但是,从上一节可以得知:java.lang.Class类的实例由JVM创建,而普通类的实例则由程序员进行创建。那么,java.lang.Class这种特殊的实例构建方法,究竟是为了什么呢,又或者说,它可以带来什么作用呢?

让我们做这样一个假设:如果对一件东西进行了特别的处理,那么那件东西一定具有特殊性。接下来,就让我们看看java.lang.Class类有什么特殊的地方:

我们都知道,Integer用来描述一个整数,String类可以用来描述一个字符串,而java.lang.Class可以对Integer、String等类型进行描述。换句话说,Integer、String用来描述一种数据类型,而java.lang.Class则是对“Integer、String等类型”进行描述的类型。读起来,有些拗口,多读三遍。

下面是一段对java.lang.Class的描述:

Instances of the class Class represent classes and interfaces in a running Java application.

在这里,只需要了解java.lang.Class类是用来描述“Integer、String等类型”的相关信息的,就可以了;而不必详尽的知道这些信息的具体内容。

3、获取java.lang.Class类的实例和简单使用

在面向对象的语言中,要使用一个东西,那么就要先获取到它。那么,在这里就是:要想使用java.lang.Class类的实例,就要先获得到java.lang.Class的实例。

3.1、获取java.lang.Class类的实例

有两种方式来获得java.lang.Class类的实例。

一种是通过普通类实例,调用其getClass()方法代码如下:

static void printClassName(Object obj)
{
	Class<?> cls = obj.getClass();
	String clsName = cls.getName();
	System.out.println(clsName);
}

下面是调用方法:

public static void main(String[] args)
{
	String str = new String("Hello world");
	printClassName(str);
	Integer iNumber = new Integer(10);
	printClassName(iNumber);
}

下面是输出的结果:

java.lang.String
java.lang.Integer

另一种是通过普通类的类名直接调用其class常量成员,

String类型代码如下:

public static void main(String[] args)
{
	Class<?> cls = String.class;
	System.out.println(cls.getName());
}

Integer类型代码如下:

public static void main(String[] args)
{
	Class<?> cls = Integer.class;
	System.out.println(cls.getName());
}

3.2、简单使用java.lang.Class类

4、forClass方法的初始化

在java.lang.Class类中,有一个静态方法:

public static Class<?> forName(String className)

这个方法的功能如下:

Returns the Class object associated with the class or interface with the given string name.

除了上面的描述外,下面这句话引起了我的注意:

A call to forName("X") causes the class named X to be initialized.

它的意思是说,调用forName("X")会让名字为“X”的类进行初始化initialized)。

我对“initialized”这个词产生了好奇:它要进行初始化(initialize),究竟要做什么工作呢?

针对这个问题,我设计一个StatisticMethod类:

package com.rk.properties;

public class StatisticMethod
{

	//001
	public static double PI = getPI();

	//002
	static
	{
		System.out.println("静态代码段");
		PI = getSecondPI();
	}

	static double getPI()
	{
		System.out.println("static void getPI()");
		return 3.14;
	}

	static double getSecondPI()
	{
		System.out.println("static double getSecondPI()");
		return 6.28;
	}

	public StatisticMethod()
	{
		System.out.println("public StatisticMethod()");
	}
}

接下来,我用Class.forName()方法对StatisticMethod类进行了调用,代码如下:

public static void main(String[] args)
{
	try
	{
		Class<?> cls = Class.forName("com.rk.properties.StatisticMethod");
		System.out.println(cls.getName());
	}
	catch (ClassNotFoundException e)
	{
		e.printStackTrace();
	}
}

执行结果如下:

static void getPI()
静态代码段
static double getSecondPI()
com.rk.properties.StatisticMethod

结果分析:

第一被调用的是:

public static double PI = getPI();

第二被调用的是静态代码段:

	static
	{
		System.out.println("静态代码段");
		PI = getSecondPI();
	}

值得注意的是,并没有调用构造函数,所以Class.forName()只是对静态变量和静态代码段进行了初始化(initialize),并没有生成类的实例对象。

时间: 2024-11-05 16:33:42

Class和 forName(String className)的作用的相关文章

Class.forName(String name)方法,到底会触发那个类加载器进行类加载行为?

4.2 在代码中直接调用Class.forName(String name)方法,到底会触发那个类加载器进行类加载行为? Class.forName(String name)默认会使用调用类的类加载器来进行类加载.我们直接来分析一下对应的jdk的代码: [java] view plain copy //java.lang.Class.java publicstatic Class<?> forName(String className) throws ClassNotFoundExceptio

collection.toArray(new String[0])中new String[0]的作用

new string[0]的作用 比如:String[] result = set.toArray(new String[0]); Collection的公有方法中,toArray()是比较重要的一个. 但是使用无参数的toArray()有一个缺点,就是转换后的数组类型是Object[]. 虽然Object数组也不是不能用,但当你真的想用一个具体类型的数组,比如String[]时,问题就来了.而把Object[]给cast成 String[]还是很麻烦的,需要用到这个: String[] str

java.lang.Class.forName(String name, boolean initialize, ClassLoader loader)方法

描述 Java.lang.Class.forName(String name, boolean initialize, ClassLoader loader) 方法返回与给定字符串名的类或接口的Class对象,使用给定的类加载器. 指定的类加载器加载的类或接口.如果该参数加载器loader 为空,通过引导类加载器加载类.当类被初始化的初始化initialize参数为true,如果它没有被初始化. 声明 以下是java.lang.Class.forName()方法的声明 [java] view p

new String[0]的作用

返回包含此 collection 中所有元素的数组:返回数组的运行时类型与指定数组的运行时类型相同.如果指定的数组能容纳 该 collection,则返回包含此 collection 元素的数组.否则,将根据指定数组的运行时类型和此 collection 的大小分配 一个新数组.如果指定的数组能容纳 collection 并有剩余空间(即数组的元素比 collection 的元素多),那么会将数组中紧 跟在 collection 末尾的元素设置为 null.(这对确定 collection 的长

java String.valueOf()的作用

在读取数据时需要对数据的强制转换,可采用String.valueOf(a),把a强制转换成字符串类型 有时候a本来就已经是字符串类型了,但是为了代码的严谨性,也会加入String.valueOf(a),这时String.valueOf(a)省略也不会出错的. 但有时会涉及到服务器的问题,所以还是加入String.valueOf(a)比较好. 使用 String.valueOf() 进行数据转换,如果被转换的数据为 null, 则这种方法将返回一个 "null" 字符串 String)

string.xml 的作用以及意义——国际化应用

为什么需要把应用中出现的文字单独存放在string.xml文件中呢? 一:是为了国际化,当需要国际化时,只需要再提供一个string.xml文件,把里面的汉子信息都修改为对应的语言(如,English),再运行程序时,android操作系统会根据用户手机的语言环境和国家来自动选择相应的string.xml文件,这时手机界面就会显示出英文.这样做国际化非常的方便. 二:为了减少应用的体积,降低数据的冗余.假设在应用中要使用"我们一直在努力"这段文字1000次,如果在每次使用时直接写上这几

String intern()的作用

Strings are a fundamental part of any modern programming language, every bit as important as numbers. So you'd think that Java programmers would go out of their way to have a solid understanding of them -- and sadly, that isn't always the case. I was

String.trim()的作用

假设有一个字符串" ddd dd d ",经过Trim()之后成为"ddd dd d",如上只去掉两边多余的空格(包括制表符). 原文地址:https://www.cnblogs.com/CatsBlog/p/9176039.html

JDBC学习2:为什么要写Class.forName(&quot;XXX&quot;)?

Class.forName(String name) 接上一篇JDBC.本来这个内容是放在前面的一篇里面的一起的,后来发现越写越多,想想看就算了,还是单独开一篇文章好了,这样也能写得更加详细点. 上一篇文章的第4点,getConnection()方法里面,我把从.properties里面获取mysqlpackage的地方替换成实际的 value值,那么替换后的应该是Class.forName("com.mysql.jdbc.Driver"),实际上所有的JDBC连接先写的基本 上也都是