Class的理解:每个类都有一个Class对象
关于静态域的处理参考第5章、第7章
Class.forName的作用
Class.forName("xx"):手动的加载某个类,不需要获得该类的Class对象;运行的结果就是加载xx类的静态域。只是为了将类加载到虚拟机中,以备你去实例化
class Foo{
static{
System.out.println("静态代码块");
}
//②普通代码块属于实例的、在没有new的时候 是不会执行的
{
System.out.println("普通的代码块");
}
//③构造器执行的时候也是和实例化有关的 所以Class.forName的时候并不会执行
private Foo(){
System.out.println("默认的构造器");
}
Foo(int i ){}
}
public class ClassDiscuss {
public static void main(String[] args) {
//Foo的类字面量
Class<Foo> foo = Foo.class;
//实例化
/* try {
Foo fooInstance = foo.newInstance();
}catch (IllegalAccessException e){
System.out.println("非法的状态访问异常");
}catch (InstantiationException e){
System.out.println("实例化出错");
}*/
try {
//①只是为了将类加载到虚拟机中 以备你去实例化
Class c = Class.forName("com.thinking.in.java.course.chapter14.Foo");
}catch (ClassNotFoundException e){
System.out.println("class Not Found");
}
}
}
获取类的继承体系
1,接口
获取所有的接口Class.forName(“xxx”).getInterfaces();
interface HasBatteries{}
interface WaterProof{}
interface Shoots{}
class Toy{
Toy(){}
Toy(int i){}
}
class FancyToy extends Toy implements HasBatteries,WaterProof,Shoots{
FancyToy(int i){
super(i);
}
}
class FancyToy2 extends Toy{
}
public class ToyTest {
static void printInfo(Class cc){
System.out.println("cc.getName: "+cc.getName()+" cc.isInterface(): "+cc.isInterface());
System.out.println("SimpleName: "+cc.getSimpleName());
System.out.println("CanonicalName: "+cc.getCanonicalName());
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("com.thinking.in.java.course.chapter14.FancyToy");
}catch (ClassNotFoundException e){
System.out.println("FancyToy not found");
System.exit(1);
}
printInfo(c);
System.out.println("==================");
//c.getInterfaces() 获取该类的所有接口
for (Class cInter : c.getInterfaces()) {
//printInfo(cInter);
if(cInter.getSimpleName().equals("WaterProof")){
//System.out.println("如何拿到其他的实现类");
}
}
}
}
2,超类
Class.forName(“xxx”).getSuperClass();
public class ToyTest {
static void printInfo(Class cc){
System.out.println("cc.getName: "+cc.getName()+" cc.isInterface(): "+cc.isInterface());
System.out.println("SimpleName: "+cc.getSimpleName());
System.out.println("CanonicalName: "+cc.getCanonicalName());
}
public static void main(String[] args) {
//拿到父类信息
Class sup = c.getSuperclass();
Object obj = null;
try {
//调用的就是默认构造器
obj = sup.newInstance();
}catch (IllegalAccessException e){
System.out.println("非法的状态异常");
System.exit(1);
}catch (InstantiationException e){
System.out.println("实例化异常");
System.exit(1);
}
printInfo(obj.getClass());
}
}
类加载的三部曲
在通过.class的时候,是不会执行类的初始化的
1,加载,由类的加载器执行,查找字节码,并通过这些字节码创建一个Class对象
2,链接,检查字节码,为静态域开辟存储空间,如果有继承体系的话,依次开辟继承体系中静态域的存储空间。
3,初始化,有父类的话,执行父类中的静态域、子类的静态域,父类的普通域、构造器,子类的普通域、构造器
对静态域的使用会执行静态域的初始化动作,但是对常数静态域的使用并不会执行初始化动作。
class Initable {
static final int STATIC_FINAL = 47;
static final int STATIC_FINAL2 = ClassInitialization.rand.nextInt(1000);
{
System.out.println("普通代码块会执行嘛?");
}
static {
System.out.println("Initializing Initable");
}
}
//详细例子参考书本
/**
对该类的非常数静态域去访问的话 会执行静态域的初始化的;
如果加上final的话,则不会执行静态域的初始化;
static final是类型安全的,高并发情况下随便使用。
*/
public class ClassInitialization {
public static Random rand = new Random(47);
public static void main(String[] args) throws Exception {
System.out.println(Initable.STATIC_FINAL);
}
}
泛化的class引用
对于有继承关系的对象而言,他们的Class对象并没有继承的关系
Class i = int.class;
Class<Integer> genericIntClass = int.class;
System.out.println(genericIntClass == i);
//Integer虽然是Number的子类,但他们的Class对象并不能这样指定,以下代码报错
// Class<Number> numberClass = Integer.class;
Class<? extends Number> numberClass = Integer.class;
//---------------只能通过泛型边界符来限定-------------------
class Goo {}
class SubGoo extends Goo{}
class Sub2Goo extends Goo{}
public class GenericClassReferences {
public static void main(String[] args) {
//Goo Class 和SubGoo Class 没有继承关系
Class<Goo> gooClass = Goo.class;
Class<? extends Goo> subGooClass = SubGoo.class;
subGooClass = Sub2Goo.class;
System.out.println( subGooClass);
}
}