首頁  >  問答  >  主體

java - 匿名內部類別和繼承類,在實作ClassLoader時為什麼會有差別

最近在看Java虛擬機,類別載入器那節舉了這麼一個例子:

/**
*类加载器与instanceof关键字演示
**
@author zzm
*/
public class ClassLoaderTest{
    public static void main(String[]args) throws Exception{
        ClassLoader myLoader=new ClassLoader(){
            @Override
            public Class<?>loadClass(String name)throws ClassNotFoundException{
                try{
                    String fileName=name.substring(name.lastIndexOf(".")+1)+".class";
                    InputStream is=getClass().getResourceAsStream(fileName);
                    if(is==null){
                        return super.loadClass(name);
                    }
                    byte[]b=new byte[is.available()];
                    is.read(b);
                    return defineClass(name,b,0,b.length);
                }
                catch(IOException e){
                    throw new ClassNotFoundException(name);
                }
            }
        }
        ;
        Object obj=myLoader.loadClass("org.fenixsoft.classloading.ClassLoaderTest").newInstance();
        System.out.println(obj.getClass());
        System.out.println(obj instanceof org.fenixsoft.classloading.ClassLoaderTest);//false
    }
}

總而言之就是用自訂的類別載入器去載入一個類,回傳的類別與jvm自帶的SystemClassLoader載入的類別不同。

那麼如果用一個繼承自ClasserLoader的類,照理說也是同樣的效果

package jvm;
public class MyClassLoader extends ClassLoader{

    @Override
    public Class<?> loadClass(String fullClassName) throws ClassNotFoundException{
        try {
            String fileName = fullClassName.substring(fullClassName.lastIndexOf(".")+1,fullClassName.length())+".class";
            InputStream is = getResourceAsStream(fileName);

            if(is==null){
                return super.loadClass(fullClassName);
            }

            byte[] bytes = new byte[is.available()];
            is.read(bytes);

            return defineClass(fullClassName,bytes,0,bytes.length);
        }catch (Exception e){
            throw new ClassNotFoundException();
        }
    }

    public static void main(String[] args) throws Exception{

        ClassLoader myClassLoader = new MyClassLoader();

        /**
        ClassLoader myClassLoader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String fullClassName) throws ClassNotFoundException {
                try {
                    String fileName = fullClassName.substring(fullClassName.lastIndexOf(".")+1,fullClassName.length())+".class";
                    InputStream is = getClass().getResourceAsStream(fileName);

                    if(is==null){
                        return super.loadClass(fullClassName);
                    }

                    byte[] bytes = new byte[is.available()];
                    is.read(bytes);

                    return defineClass(fullClassName,bytes,0,bytes.length);
                }catch (Exception e){
                    throw new ClassNotFoundException();
                }
            }
        };
        /**/

        ClassLoader systemClassLoader = java.lang.ClassLoader.getSystemClassLoader();

        Class myClass = myClassLoader.loadClass("jvm.MyClassLoader");
        Class systemClass = systemClassLoader.loadClass("jvm.MyClassLoader");

        Object myObj = myClass.newInstance();
        Object systemObj = systemClass.newInstance();

        System.out.println(myClass.equals(systemClass));//true
        System.out.println(myObj.getClass().equals(systemObj.getClass()));//true

    }
}

註解裡的程式碼就是匿名內部類別的繼承,注意到這裡myClass和systemClass是完全相等的,但myClass是用繼承自ClassLoader的類別MyClassLoader產生的,請問這是為什麼。 。 。

PHP中文网PHP中文网2733 天前756

全部回覆(1)我來回復

  • 巴扎黑

    巴扎黑2017-05-17 10:09:45

    第二個程式碼走到

    if(is==null){
        return super.loadClass(fullClassName);
    }

    加載class文件用getClass().getResourceAsStream

    回覆
    0
  • 取消回覆