簡體   English   中英

當不同的類加載器提供一個類的多個版本時,如何引用一個特定的版本?

[英]When multiple versions of a class are made available by different class loaders, how can I reference a particular one?

此問題源於IntelliJ GUI設計器,該設計器似乎在包含其自己的舊版本MigLayout的環境中加載自定義表單組件。

如果我創建一個使用MigLayout的自定義組件:

import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
public class ComponentUsingMigLayout extends JPanel {
   public ComponentUsingMigLayout() {
      try {
         setLayout(new MigLayout(new LC().insets("20")));
         add(new JButton("Hello"), new CC().cell(0, 0));
      }
      catch (Throwable t) {
         JOptionPane.showMessageDialog(null, t.toString());
      }
   }
}

然后創建一個GUI窗體,執行“向組件添加組件”,然后選擇ComponentUsingMigLayout ,我看到帶有java.lang.NoSuchMethodError: net.miginfocom.layout.CC.cell([I)Lnet/miginfocom/layout/CC消息對話框java.lang.NoSuchMethodError: net.miginfocom.layout.CC.cell([I)Lnet/miginfocom/layout/CC

我猜這是因為IntelliJ加載了自己的MigLayout版本,該版本可用於表單組件,而這是一個缺少可變參數cell()方法的舊版本。 我知道,由於對"com.miglayout" % "miglayout-core" % "4.2"的依賴,因此MigLayout的較新版本也應可用於運行時。

這是一個完整的示例,其中包含IDEA項目文件

有沒有一種方法可以強制使用"com.miglayout" % "miglayout-core" % "4.2"

解決方案是檢測GUI設計器正在加載類的情況,並剖析類加載器以刪除父類:

package guidesignermiglayout;

import javax.swing.*;
import java.awt.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

@SuppressWarnings({"unchecked", "ToArrayCallWithZeroLengthArrayArgument"})
public class ComponentUsingMigLayout extends JPanel {
   public ComponentUsingMigLayout() {
      try {
         ClassLoader cl = getClass().getClassLoader();

         ClassLoader localCL;
         if (cl.getClass().getName().contains("DesignTimeClassLoader")) {
            localCL = new URLClassLoader(((List<URL>) cl.getClass().getMethod("getUrls").invoke(cl)).toArray(new URL[]{}));
         }
         else {
            localCL = cl;
         }

         Class migLayout = localCL.loadClass("net.miginfocom.swing.MigLayout");

         Class lc = localCL.loadClass("net.miginfocom.layout.LC");
         Method insets = lc.getDeclaredMethod("insets", String.class);

         Class cc = localCL.loadClass("net.miginfocom.layout.CC");
         Method cell = cc.getDeclaredMethod("cell", int[].class);

         setLayout((LayoutManager) migLayout.getConstructor(lc).newInstance(
              insets.invoke(lc.newInstance(), "20")
         ));
         add(new JButton("Hello"), cell.invoke(cc.newInstance(), new Object[]{new int[]{0, 0}}));
      }
      catch (Throwable t) {
         JOptionPane.showMessageDialog(null, t.toString());
      }
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM