Class的理解:每个类都有一个Class对象

关于静态域的处理参考第5章、第7章

Class.forName的作用

  1. 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");
        }

    }
}

获取类的继承体系

从下往上拿类型的信息操作方式:
image.png

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对象并没有继承的关系
image.png

 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);
    }
}