如何在受保护的 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 使用字节码注入,并在运行时设置接口。不过,这很棘手。
也许还有一种方法可以通过反射来改变交互,但我对此表示怀疑。
私人存在是有原因的。
【讨论】:
我认为这行不通。字节码注入方法很可能导致VerifyError
或IncompatibleClassChangeError
。此外,您不能通过反射来更改接口......但您可以反射地调用私有方法。以上是关于如何在受保护的 java 类上实现接口的主要内容,如果未能解决你的问题,请参考以下文章
在 Object[] 数组上实现 Java Iterator 和 Iterable 接口
如何在受保护的 Word 文档中使用 Word RepeatingSection ContentControl