簡體   English   中英

java-其名稱在編譯時已知,並且在運行時擴展了其他類的類

[英]java - Class whose name is known at compile time and which extends other class at runtime

我希望創建一個輔助適配器(超級)類的開源實現(子類)。 我有兩個不同的要求:

  1. 我需要在運行時而不是在編譯時擴展子類
  2. 我的子類的類名必須在編譯時知道。

用例:由於超類具有專有許可證,因此我不能在其開源項目的構建中包括其源代碼,也不能引用預構建的二進制文件。 我的子類的實際運行時用法將發生在專有的封閉源代碼框架代碼中。 該框架將按名稱創建我的子類的實例。 因此,我的子類名稱需要事先知道。

后一個問題似乎排除了諸如cglib之類的在運行時創建新類名的方法。

示例代碼:

package com.proprietary;
public class Adapter {}

package org.free;
public class AdapterImpl
    // com.proprietary is not available at compile time
    // extends com.proprietary.Adapter 
{}

package com.proprietary;
public class Framework {

     public static void main(String[] args) {
         // Simplified: class name is not hard-coded in reality,
         // but comes from external config
         Class c = Class.forName("org.free.AdapterImpl");
         ...
     }
}

也許簽出ByteBuddy

您可以動態創建一個新類,其功能可以幫助支持您的約束:

  • 使用Class.forName加載第三方專有類而不在代碼中鏈接到它,您將類名作為配置點傳遞
  • 命名策略使您可以控制生成的類的名稱
  • intercept( 實現 )插入您的自定義代碼。

例:

Class<?> dynamicType = new ByteBuddy()
  .subclass(Class.forName(thatPeskyProprietaryClass))
  .namingStrategy(...)
  .method(ElementMatchers.named("someMethod"))
  .intercept(...)
  .make()
  .load(getClass().getClassLoader())
  .getLoaded();

走錯了兔子洞。

首先,這是不可能的:您不能在運行時擴展類。 類的性質在編譯時是“固定的”。 然后寫入一個包含該“性質”的.class文件。 此后無法更改。 C級為C級; 並且您不能在運行時“增強” C來使C extends D突然C extends D

除此之外:僅當您打算利用多態性時,創建子類才有意義。

含義:

class A { }
class B extends A {}

很有意義……當您的“客戶端代碼”同時使用類名A和B時(大多數情況下)。

因此,除非我們談論的是某個框架,其中“您的”對象需要擴展A以允許在該框架中集成,否則強迫您的B擴展“以后”擴展不會帶來太多好處 因為如前所述:在您的源代碼(編譯器視圖)中,B不會是A; 因此您無法編寫任何受益於B擴展A的代碼。

因此,在這里我可以看到“最接近”的東西:使用composition 您的類應包含一個指向該庫類實例的字段; 並且該實例是使用反射創建的。

然后, 您的類提供了一個簡潔的界面來訪問A中可以找到的行為。

暫無
暫無

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

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