java 子类 类名_java中Class对象详解和类名.class, class.forName(), getClass()区别

A a = new A();

if(a.getClass()==A.class) {

System.out.println("equal");

} else {

System.out.println("unequal");

}

输出equal;

可以看到,对象a是A的一个实例,A是某一个类,在if语句中使用a.getClass()返回的结果正是类A的类型类,在Java中表示一个特定类型的类型类可以用“类型.class”的方式获得,因为a.getClass()获得是A的类型类,也就是A.class,因此上面的代码执行的结果就是打印出“equal”。特别注意的是,类型类是一一对应的,父类的类型类和子类的类型类是不同的,因此,假设A是B的子类,那么如下的代码将得到“unequal”的输出:

A a = new A();

if(a.getClass()==B.class) {

System.out.println("equal");

}  else {

System.out.println("unequal");

}

输出unequal;

因此,如果你知道一个实例,那么你可以通过实例的“getClass()”方法获得该对象的类型类,如果你知道一个类型,那么你可以使用“.class”的方法获得该类型的类型类。

2,获得类型的信息

在获得类型类之后,你就可以调用其中的一些方法获得类型的信息了,主要的方法有:

getName():String:获得该类型的全称名称。

getSuperClass():Class:获得该类型的直接父类,如果该类型没有直接父类,那么返回null。

getInterfaces():Class[]:获得该类型实现的所有接口。

isArray():boolean:判断该类型是否是数组。

isEnum():boolean:判断该类型是否是枚举类型。

isInterface():boolean:判断该类型是否是接口。

isPrimitive():boolean:判断该类型是否是基本类型,即是否是int,boolean,double等等。

isAssignableFrom(Classcls):boolean:判断这个类型是否是类型cls的父(祖先)类或父(祖先)接口。

getComponentType():Class:如果该类型是一个数组,那么返回该数组的组件类型。

此外还可以进行类型转换这类的操作,主要方法有:

asSubclass(Class clazz):Class:将这个类型

-----------------------------------------------------------------------------------

在学习反射时想到了这个问题,.getClass()和.class有没有什么区别?

当然,最明显的区别就是.getClass()是一个对象实例的方法,只有对象实例才有这个方法,具体的类是没有的。类的Class类实例是通过.class获得的,显然,类没有.getClass()方法。

从网上还找到一些其他资料:

1、出现的时期不同:Class.forName()在运行时加载;Class.class和getClass()是在编译时加载.

这里有些个疑问?Class.forName("XXX")这方法是动态加载class,先把类文件加载进来,再使用.newInstance()时创建了一个对象。

new ClassName(),就是所谓的静态加载,

Class.forName("ClassName"),就是所谓的动态加载。

区别在于“静态加载”的类在编译的时候就要提供,而动态加载的类在源程序编译时可以缺席,在运行时按需提供。

Class.forName(xxx.xx.xx) 返回的是一个类, .newInstance() 后才创建一个对象 Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段

2、 举个例子,Iterator it = s.iterator();得到的it的真正类型是KeyIterator,是Iterator的子类,按常理来说应该可以执行next()方法,但是值 得注意的是,KeyIterator是hashmap的内部类,JAVA给的提示是cannot access a member of class java.util.HashMap$KeyIterator withmodifiers "public"

从上面的那些例子上也能看出,除内部类外的其他类的应用上.class功能完全等于.getClass()!只是一个是用类直接获得的,一个是用实例获得的。

-------------------------------------------------------------------------------------------------------------------------------------------

Class对象的生成方式如下:

1.类名.class           说明: JVM将使用类装载器, 将类装入内存(前提是:类还没有装入内存),不做类的初始化工作.返回Class的对象

2.Class.forName("类名字符串")  (注:类名字符串是包名+类名)  说明:装入类,并做类的静态初始化,返回Class的对象

3.实例对象.getClass()  说明:对类进行静态初始化、非静态初始化;返回引用运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象

通过下面的程序,来观察一下Class对象的生成的原理。

package ClassTest;

public class TestClass {

public static void main(String[] args) {

try {

// 测试.class

@SuppressWarnings("rawtypes")

Class testTypeClass = TestClassType.class;

System.out.println("testTypeClass---" + testTypeClass);

// 测试Class.forName()

@SuppressWarnings("rawtypes")

Class testTypeForName = Class.forName("ClassTest.TestClassType");

System.out.println("testTypeForName---" + testTypeForName);

// 测试Object.getClass()

TestClassType testTypeGetClass = new TestClassType();

System.out.println("testTypeGetClass---"

+ testTypeGetClass.getClass());

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

package ClassTest;

public class  TestClassType {

// 构造函数

public TestClassType() {

System.out.println("----构造函数---");

}

// 静态的参数初始化

static {

System.out.println("---静态的参数初始化---");

}

// 非静态的参数初始化

{

System.out.println("----非静态的参数初始化---");

}

}

运行结果如下

testTypeClass---class ClassTest.TestClassType

---静态的参数初始化---

testTypeForName---class ClassTest.TestClassType

----非静态的参数初始化---

----构造函数---

testTypeGetClass---class ClassTest.TestClassType

然而单独执行测试Class.forName() 时结果为

---静态的参数初始化e---

testTypeForName---测试Class.forName()/class ClassTest.TestClassType

单独执行测试Object.getClass() 结果为

---静态的参数初始化e---

----非静态的参数初始化e---

----构造函数e---

testTypeGetClass---测试Object.getClass()/class ClassTest.TestClassType

所以根据结果可以发现,三种生成的Class对象一样的。并且程序只打印一次“静态的参数初始化”,但时拆分单独执行时class.forName(),Object.getClass()时

都执行了“静态的参数初始化”。

我们知道,静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new 类实例对象的时候加载。

因此,这段程序说明,三种方式生成Class对象,其实只有一个Class对象。在生成Class对象的时候,首先判断内存中是否已经加载。

所以,生成Class对象的过程其实是如此的:

当我们编写一个新的java类时,JVM就会帮我们编译成class对象,存放在同名的.class文件中。在运行时,当需要生成这个类的对象,JVM就会检查此类是否已经装载内存中。若是没有装载,则把.class文件装入到内存中。若是装载,则根据class文件生成实例对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值