type information - The Class Object

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/wangbingfengf98/article/details/94492635

The class loader first checks to see if the Class Object for that type is loaded. If not, the default class loader finds the .class file with that name (an add-on class loader might, for example, look for the bytecodes in a database instead).

  • Each class object is loaded only when it's needed.
  • The static initialization is performed upon class loading.

forName

public static Class<?> forName(String className)
                        throws ClassNotFoundException

Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:

Class.forName(className, true, currentLoader)

where currentLoader denotes the defining class loader of the current class.

For example, the following code fragment returns the runtime Class descriptor for the class named java.lang.Thread:

Class t = Class.forName("java.lang.Thread")

A call to forName("X") causes the class named X to be initialized.

Parameters:

className - the fully qualified name of the desired class.

Returns:

the Class object for the class with the specified name.

Throws:

LinkageError - if the linkage fails

ExceptionInInitializerError - if the initialization provoked by this method fails

ClassNotFoundException - if the class cannot be located

For example

// typeinfo/SweetShop.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Examination of the way the class loader works

class Cookie {
  static {
    System.out.println("Loading Cookie");
  }
}

class Gum {
  static {
    System.out.println("Loading Gum");
  }
}

class Candy {
  static {
    System.out.println("Loading Candy");
  }
}

public class SweetShop {
  public static void main(String[] args) {
    System.out.println("inside main");
    new Candy(); // static method class
    System.out.println("After creating Candy");
    try {
      Class.forName("Gum"); // [1]
    } catch (ClassNotFoundException e) {
      System.out.println("Couldn't find Gum");
    }
    System.out.println("After Class.forName(\"Gum\")");
    new Cookie();
    System.out.println("After creating Cookie");
  }
}
/* 
execute
$ ./gradlew :typeinfo:SweetShop

Output:
inside main
Loading Candy
After creating Candy
Loading Gum
After Class.forName("Gum")
Loading Cookie
After creating Cookie
*/

when run above example in Eclipse, [1] will throw ClassNotFoundException

    /**
     * Returns the {@code Class} object associated with the class or
     * interface with the given string name.  Invoking this method is
     * equivalent to:
     *
     * <blockquote>
     *  {@code Class.forName(className, true, currentLoader)}
     * </blockquote>
     *
     * where {@code currentLoader} denotes the defining class loader of
     * the current class.
     *
     * <p> For example, the following code fragment returns the
     * runtime {@code Class} descriptor for the class named
     * {@code java.lang.Thread}:
     *
     * <blockquote>
     *   {@code Class t = Class.forName("java.lang.Thread")}
     * </blockquote>
     * <p>
     * A call to {@code forName("X")} causes the class named
     * {@code X} to be initialized.
     *
     * @param      className   the fully qualified name of the desired class.
     * @return     the {@code Class} object for the class with the
     *             specified name.
     * @exception LinkageError if the linkage fails
     * @exception ExceptionInInitializerError if the initialization provoked
     *            by this method fails
     * @exception ClassNotFoundException if the class cannot be located
     */
    @CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        return forName0(className, true,
                        ClassLoader.getClassLoader(Reflection.getCallerClass()));
    }

Basically, the @CallerSensitive annotation is used by the JVM

The JVM will track this annotation and, optionally, enforce the invariant that the sun.reflect.Reflection.getCallerClass method can only report the caller of a method when that method is marked with this annotation.

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/typeinfo/SweetShop.java

3. https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#forName-java.lang.String-

4. https://stackoverflow.com/questions/22626808/what-does-the-sun-reflect-callersensitive-annotation-mean

5. http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Class.java

猜你喜欢

转载自blog.csdn.net/wangbingfengf98/article/details/94492635
今日推荐