type information - The Class Object

本文深入探讨了Java类加载过程,解析了类加载器如何按需加载类对象,并执行静态初始化。通过具体示例,展示了Class.forName方法的使用,包括其参数、返回值及可能抛出的异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值