Class对象:class对象包含了与类有关的信息,每个类都有一个Class对象,每当我们编写并且编译了一个新类就会产生一个Class对象。
Class作用:用来创建一个类的实例(对象),执行RTTI(运行时类型信息);
Class.foName():通过该方法,获得一个类的Class对象的引用。从而可以在运行时使用类型信息。从而在对象还没有没有被new的时候去执行所有的静态域(包括静态域的初始化)。
package com.package14;
class Candy {
static {
System.out.println("gandy 糖果");
}
}
class Gum {
static {
System.out.println("Gum 口香糖");
}
}
class Cookie {
static {
System.out.println("cookie 曲奇");
}
}
public class SweetShop {
public static void main(String[] args) {
System.out.println("inside main");
new Candy();
System.out.println("After creating Gandy");
try {
//手动去加载Gum类,从而在运行时使用该类的类型信息(加载类中的静态域)
Class.forName("com.package14.Gum");
} catch (ClassNotFoundException e) {
System.err.println("not found Gum");
}
System.out.println("After Class.foName()");
new Cookie();
System.out.println("After creating Cookie");
}
}
同时,使用Class。forName或一个类的Class引用后,该引用将会被加载到内存中去,以备我们去实例化。<br /> 获取详细的类型信息:<br /> 1.获取类中的信息:
interface HasBatteries { }
interface Waterproof { }
interface Shoots { }
class Toy { Toy() { }
Toy(int i) { }
}
class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots {
FancyToy() { super(1);}
}
public class ToyTest {
static void info(Class cc) {//通过类Class 对象拿到该类的类型信息
System.out.println("Class Name:" + cc.getName());
System.out.println("Class is interface:" + cc.isInterface());
System.out.println("Simple name:" + cc.getSimpleName());
System.out.println("Canonical name" + cc.getCanonicalName());
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("com.package14.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("Can't find FancyToy");
System.exit(1);//参数不为0是停止虚拟机
}
info(c);//获得FanyToy类的类型信息
获取类的继承体系(从下往上)
1.获取类实现的接口:
①先拿到类的Class对象②:使用getInterfaces方法
package com.package14;
interface HasBatteries { }
interface Waterproof { }
interface Shoots { }
class Toy { Toy() { }
Toy(int i) { }
}
class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots {
FancyToy() { super(1);}
}
public class ToyTest {
static void info(Class cc) {//通过类Class 对象拿到该类的类型信息
System.out.println("Class Name:" + cc.getName());
System.out.println("Class is interface:" + cc.isInterface());
System.out.println("Simple name:" + cc.getSimpleName());
System.out.println("Canonical name" + cc.getCanonicalName());
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("com.package14.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("Can't find FancyToy");
System.exit(1);//参数不为0是停止虚拟机
}
info(c);//获得FanyToy类的类型信息
System.out.println("该类中实现的接口有");//拿到fancyToy类中实现的接口
for (Class cInterface : c.getInterfaces()) {
System.out.println(cInterface);
}
2.获取超类信息(父类):
①:获得该类的Class对象②:使用getSuperclass方法拿到父类③:newInstance()创建父类,然后在拿取父类的信息
public class ToyTest {
static void info(Class cc) {//通过类Class 对象拿到该类的类型信息
System.out.println("Class Name:" + cc.getName());
System.out.println("Class is interface:" + cc.isInterface());
System.out.println("Simple name:" + cc.getSimpleName());
System.out.println("Canonical name" + cc.getCanonicalName());
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("com.package14.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("Can't find FancyToy");
System.exit(1);//参数不为0是停止虚拟机
}
Class superclass = c.getSuperclass();//获得该类的父类
Object obj=null;
System.out.println("父类的类信息为:");
try {
obj=superclass.newInstance();//创建父类
} catch (InstantiationException e) {
System.out.println("实例化异常");
System.exit(1);
} catch (IllegalAccessException e) {
System.out.println("访问异常");
System.exit(1);
}
info(obj.getClass());//拿到父类的信息
}
}
使用类时的三部曲:
加载.class的时候不会执行初始化
加载:由类加载器执行,会去查找类的字节码,并从这些字节码中创建一个Class对象
链接:验证类的字节码,并为静态域没分配空间
初始化:执行初始化,先父类的静态域、子类静态域,然后父类普通域、构造器。子类普通域、构造器
对静态域的调用会执行静态域的初始化操作,对于常数静态域的掉用则不会。静态常数可以在高并发的时候随意使用
package com.package14;
class StaticDemo1{
static final int SFI= 47;
static{
System.out.println("执行初始化11111");
}
}
class StaticDemo2{
static int SFI= 47;
static{
System.out.println("执行初始化11111");
}
}
public class ClassInitallization2 {
public static void main(String[] args) {
System.out.println(StaticDemo1.SFI);
System.out.println(StaticDemo2.SFI);
}
}
泛化的class引用
class的引用表示的就是他所指的对象的确切类型,我们也可以使用泛型,对其所指的类型进行限定。
注意:每个类的Class对象都是不同的,所以对有继承关系的类来说,他们的Class对象之间没有继承关系
package com.package14;
public class GenericClasss {
public static void main(String[] args) {
Class<Integer> ints = int.class;
Class integerClassass = int.class;
//同一个对象的Class对象相等
System.out.println(ints==integerClassass);
//Integer虽然是Number的子类,但他们的Class对象并不能这样指定,以下代码报错
//Class<Number> numberClass = Integer.class;
//只能通过泛型边界符来指定
Class<?extends Number> numberClass1 = Integer.class;
}
}
/*===========================================================================*/
package com.package14;
class Goo{}
class SubGoo extends Goo{}
class SubGoo2 extends Goo{}
class SubGoo3{}
public class GenericClassReferences {
public static void main(String[] args) {
//SubGooClass 和GooClass没有继承关系
Class<? extends Goo> subGooClass = SubGoo.class;//通过通配符可以指定
subGooClass=SubGoo2.class;//也可以指定其他
//subGooClass=SubGoo3.class;//不在一个继承体系不可以,除非通配符指向Object
}
}