Java - 是否可以初始化所有类

时间:2013-11-19 22:42:08

标签: java class initialization

我想知道是否有可能初始化所有类。

这是因为我在一个基本上没有反射的环境中工作。所以我的第一个想法是初始化所有类,以便我想在某处注册的某些类在那里注册而无需为所有类输入代码。

但我基本上只是注意到在不知道它是哪个类的情况下静态实例化类的对象是不可能的。

所以我要求的一切都是毫无意义的,我恐怕不能做我最初想做的事情。注册一堆我不想手工完成的课程。

“Class”类的功能也非常有限。我不能从Class对象创建一个实例,这使得这完全不可能(我也不能从类对象中调用静态的东西)!

如果需要更多信息,请告诉我。

5 个答案:

答案 0 :(得分:5)

不,并非所有课程都可以初始化 证明:

public class ThisClassCannotBeInitialized {

    static int ohGodWhy = 1 / 0;
}

尝试初始化此类将产生java.lang.ExceptionInInitializerError

答案 1 :(得分:3)

你的建议是不太可能是一个好主意。有时候做的是找到带注释的所有类或实现一个接口。这是一个图书馆。

https://code.google.com/p/reflections/

  

Reflections会扫描您的类路径,索引元数据,允许您在运行时查询它,并可以保存和收集项目中许多模块的信息。

     

使用思考可以查询元数据,例如:

     
      
  • 获取某种类型的所有子类型
  •   
  • 获取所有使用某些注释注释的类型/构造/方法/字段,可选择使用与注释参数匹配
  •   
  • 获取与正则表达式匹配的所有资源
  •   
  • 获取具有特定签名的所有方法,包括参数,参数注释和返回类型
  •   

答案 2 :(得分:2)

取自JLS 12.4.1

  

类或接口类型T将在第一次出现以下任何一个之前立即初始化:

     
      
  • T是一个类,并创建了一个T实例。

  •   
  • T是一个类,调用T声明的静态方法。

  •   
  • 分配由T声明的静态字段。

  •   
  • 使用T声明的静态字段,该字段不是常量   变量(§4.12.4)。

  •   
  • T是顶级课程(第7.6节)和断言声明(第14.10节)   执行词汇嵌套在T(§8.1.3)中。

  •   

因此,如果您想在某个时间点初始化项目中的所有类,那么您必须遍历您的类并对要初始化的每个类执行上述操作之一。你也可以吗?理论上,当然。实际上,如果你依赖必须在某个特定时间点初始化项目中的每个类,那么你几乎肯定会采取错误的方式。

答案 3 :(得分:0)

我不知道这样做的简单方法。您不一定知道应用程序最终将最终加载的整个类集。您可以遍历整个类路径查找类,并逐个加载和初始化它们,但这非常低效,并且您可能最终会处理许多您从未加载过的类。

如果您只需要分段或从预定义列表初始化某些类,您可以使用下面的RuntimeHelpers.encureClassInitialized()方法:

public final class RuntimeHelpers {
    private RuntimeHelpers() {
        throw new IllegalStateException("Code is supposed to be unreachable.");
    }

    public static void ensureClassInitialized(final Class<?> clazz) {
        getUnsafeInstance().ensureClassInitialized(Objects.requireNonNull(clazz, "clazz"));
    }

    private static Unsafe _unsafe;

    private static Unsafe getUnsafeInstance() {
        if (_unsafe != null) {
            return _unsafe;
        }

        try {
            return (_unsafe = Unsafe.getUnsafe());
        }
        catch (Throwable ignored) {
        }

        try {
            final Field instanceField = Unsafe.class.getDeclaredField("theUnsafe");
            instanceField.setAccessible(true);
            _unsafe = (Unsafe) instanceField.get(Unsafe.class);
        }
        catch (Throwable t) {
            throw new IllegalStateException(
                String.format(
                    "Could not load an instance of the %s class.",
                    Unsafe.class.getName()
                )
            );
        }

        return _unsafe;
    }
}

警告,此代码依赖于JDK内部,可能(理论上)在不同版本之间进行更改,甚至可以完全删除。它可能在非Oracle JDK上根本不起作用。

答案 4 :(得分:-3)

这应该可以解决问题

List<class> allClassess = HelloWorld.GetClasses();

foreach (currentClass class in  allClassess )
    currentClass.Initialize();