如何在受保护的 java 类上实现接口

Posted

技术标签:

【中文标题】如何在受保护的 java 类上实现接口【英文标题】:How to implement an interface on a protected java class 【发布时间】:2011-06-12 04:16:03 【问题描述】:

我希望在包私有 java 类上实现一个接口,但我在实现这一点时遇到了一些困难。下面是一个例子。

class Foo

    String something(String str)
    
        return ""str+"!";
    





public interface Bar

    String something(String str);

这里最好的方法是什么?我的最终目标是在 Foo 类上实现 Bar 接口。我希望能够将 Foo 转换为 Bar: (Bar)Foo

Bar 接口和 Foo 类位于不同的包中。有没有办法做到这一点?

请指教。

【问题讨论】:

【参考方案1】:

Foo 需要实现 Bar

protected class Foo implements Bar

另外,我认为 Foo.something 需要 public 才能实现 Bar.something

旁注:虽然这可能只是一个例子,

return ""str+"!";

应该是:

return str + "!";

如果 Foo 是包私有的,而您无权访问源代码,只有类文件和/或包含 Foo.class 的 jar,则没有什么可做的 - 包私有的东西对中的类是不可见的默认包(没有指定包的地方)和其他包。

【讨论】:

Foo.something 不公开,我无权访问 你知道 Foo.something 是否至少受到保护?根据你的例子, Foo.something 是包可见的,我不知道我们能做多少。 @andersra:“我无权访问”是什么意思? Foo 是包私有的,接口在另一个包中。我编辑了原始问题以反映这一点,抱歉。【参考方案2】:

如果您无法控制某个类,但您想让它看起来像您拥有的 API,那么您可以 Adapt 它来满足您的需求。提示:适配器模式

【讨论】:

【参考方案3】:

如果您无权访问Foo 的源代码,则需要使用继承或组合。

// By logically including your code in the package containing Foo,
// you can now access it. If Foo belongs to the default package, sorry.
// This also doesn't work if the package is sealed.
package where.foo.resides;

public interface Bar 
    String something(String s);


// Inheritance
public class FooBar extends Foo implements Bar 
    public String something(String s) 
        return super.something(s);
    


// Composition
public class ComposedFooBar implements Bar 
    private final Foo delegate;
    public ComposedFooBar(Foo delegate) 
        this.delegate = delegate;
    
    public String something(String s) 
        return delegate.something(s);
    

【讨论】:

我的错误,如果 Foo 是包私有的,这个解决方案是否仍然适用? 视情况而定。如果Foo 在一个密封的JAR 文件中并且您没有源代码,那么您就不走运(没有反射),因为您无法在其包之外引用Foo 类型。情况可能并非如此,因此您仍然可以创建一个以package foo; 或任何包含Foo 的包开头的文件并使用这种方法。【参考方案4】:

你不能。让包级别访问它以精确避免在外面看到该类。但是,您可以做的事情(授予 Foo 不是最终的)是这样的:

C:\>type *.java
//Foo.java
package foo;
class Foo 
  String something( String s ) 
    return s + "!";
  
  
//Bar.java
package bar;
public interface Bar 
  public String something( String s );
    
//Baz.java
package foo;    
import bar.Bar;    
public class Baz extends Foo implements Bar 
  // make sure you're overriding
  @Override
  public String something ( String s ) 
    return super.something( s );
  
     
//Use it: Main.java
package bar;
import foo.Baz;   
class Main 
  public static void main( String ... args ) 
    Bar bar = new Baz();
    System.out.println( bar.something("like this?"));
  


C:\>java bar.Main
like this?!

哒哒!

诀窍是在与父级相同的包中定义子级,以便您可以创建它的公共版本。

我希望这会有所帮助。

【讨论】:

这是我最初采用的方法,但我收到错误消息:“Foo 中的某物(字符串)无法在 Bar 中实现某物(字符串),试图分配较弱的访问权限;是公开的 我也明白了。然后刚刚添加:public String something( String s ) return super.something( s ); 您可以复制我提供的代码并自己查看。 这就是为什么有必要用返回super.something(s)的公共版本覆盖something(s) 可能你拼错了覆盖的方法添加Override注解。查看更新【参考方案5】:

您可以尝试通过 BCEL 或 ASM 使用字节码注入,并在运行时设置接口。不过,这很棘手。

也许还有一种方法可以通过反射来改变交互,但我对此表示怀疑。

私人存在是有原因的。

【讨论】:

我认为这行不通。字节码注入方法很可能导致VerifyErrorIncompatibleClassChangeError。此外,您不能通过反射来更改接口......但您可以反射地调用私有方法。

以上是关于如何在受保护的 java 类上实现接口的主要内容,如果未能解决你的问题,请参考以下文章

如何调用在受SSL保护的服务器上运行的API

在 Object[] 数组上实现 Java Iterator 和 Iterable 接口

如何在受保护的 Word 文档中使用 Word RepeatingSection ContentControl

如何在接口上实现静态方法?

如何使用 Xamarin Android 在 Edit Text 上实现 TextWatcher 接口?

自定义 UnmarshalYAML,如何在自定义类型上实现 Unmarshaler 接口