【问题标题】:Class with alternative name具有替代名称的类
【发布时间】:2013-11-29 02:56:14
【问题描述】:

我有一个使用库的 javaprogramm,其中包名几乎随每个新版本而变化。

我希望我的程序在多个版本的库上运行。我认为可以为一个类创建一个别名:

my.class.????.path -> my.class.path

我可以得到 ????通过使用 class.getName() 和拆分,我只需要一种方法来告诉类加载器将类 my.class.???.path 与另一个路径链接,这样我就可以使用 在使用我的类加载器加载的类中导入 me.class.path

我有一个版本,其中我有很多文件,使用不同的导入,我根据使用的 libaryversion 加载它们,但这是使用更多资源,我希望我的程序保持小。

我希望有人可以帮助我。

狮子座

【问题讨论】:

  • 停止使用该库。
  • 尝试寻找另一个库...
  • 只是好奇,你在写什么库?更改包名称(?!?)并因此更改库的整个结构with almost every release...
  • @StackOverflowException 我在库中使用了不打算使用的类,就是它们更改了名称,我需要访问它们才能使我的程序正常工作。
  • 我正在使用bukkit,我需要访问不应该使用的 api 类。

标签: java class classloader classname


【解决方案1】:

你不能。

或者至少它不是那么微不足道/明智的。 看看这个非常简单的 Java 程序:

import java.util.Random;

public class Simple {

    public static void main(String[] args) {
        Random r = new Random();
        System.out.println(r.nextInt());
    }

}

使用javac Simple.java 将产生以下.class 文件(javap -c Simple):

Compiled from "Simple.java"
public class Simple {
  public Simple();
  Code:
     0: aload_0       
     1: invokespecial #1 // Method java/lang/Object."<init>":()V
     4: return        

  public static void main(java.lang.String[]);
  Code:
     0: new           #2 // class java/util/Random
     3: dup           
     4: invokespecial #3 // Method java/util/Random."<init>":()V
     7: astore_1      
     8: getstatic     #4 // Field    java/lang/System.out:Ljava/io/PrintStream;
    11: aload_1       
    12: invokevirtual #5 // Method java/util/Random.nextInt:()I
    15: invokevirtual #6 // Method java/io/PrintStream.println:(I)V
    18: return        
}

如您所见,类名是完全限定的,因此如果不使用库为ASM 操作字节码,您将不会更改它们。

但是,这可能的:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Simple {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class cl = Class.forName("java.util.Random");
        Object r = cl.newInstance();
        Method nextIntMethod = cl.getMethod("nextInt");
        int randomInt = (Integer) nextIntMethod.invoke(r);
        System.out.println(randomInt);
    }

}

虽然这样很麻烦。

请注意,使用反射的解决方案从 2 行增加到 5 行。 此外,您仍然需要按版本获取 FQCN。不然会炸的!

【讨论】:

  • 我知道如何获取 FQCN。我使用反射来获取一个类,然后我可以拆分类名来提取包。
  • 我知道如何获取 FQCN。我使用反射来获取一个类,然后我可以拆分类名来提取包。我认为使用类加载器可能是可能的。我已经有了一个类加载器,我可以在其中更改要搜索的类(通过覆盖 loadClass() 和 findClass() 方法),但随后我得到一个 NoClassDefFoundError ,这意味着没有找到 ClassDefinition。如果我知道如何重写将 ClassDefinition 分配给 ClassName 的方法,我可以做到。但是异常中没有显示错误的确切路径。
猜你喜欢
  • 2011-02-25
  • 1970-01-01
  • 2017-01-22
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 2019-05-29
  • 2015-07-23
相关资源
最近更新 更多