我有一个看起来像这样的课程:
class A {
public void method1(){
iniCall();
// Do something
finalCall();
}
public void method2(){
iniCall();
// Do something different
finalCall();
} // ... more methods like this
}
如何简化此iniCall
和finalCall
以便不要在每个函数(或多个函数)中编写它们?
是否可以执行call(method1)
之类的操作,如下所示:
public void call(method){
iniCall();
method();
finalCall();
}
否则,什么是好的选择?
答案 0 :(得分:12)
修改强> 我看到我的答案提出了一些问题。
Runnable接口应由任何其实例由线程执行的类实现。
因此,创建此接口的实例可能会导致不确定性和问题。正如评论中所建议的那样,您可能希望编写自己的界面并使用它。它可能是这样的:
public interface Method {
public void run();
}
您的call
方法将更改为以下内容:
public void call(Method method) {
iniCall();
method.run();
finalCall();
}
你对这种方法的调用将是这样的:
call(new Method() {
public void run() {
// do your stuff here
}
});
我建议您使用类似的设计或考虑使用模板模式,这可能需要进行一些重构。
答案 1 :(得分:12)
如果不使用Java 8,可以使用lambda表达式(或实现Runnable
的匿名类实例):
public void call(Runnable method){
iniCall();
method.run();
finalCall();
}
...
public void someMethod () {
call (() -> {
// do something
});
...
call (() -> {
// do something different
});
}
答案 2 :(得分:5)
与其他建议(比我快得多 - 但我总是希望提供正在运行的示例...)类似,我建议传递Runnable
实例到一般调用iniCall()
的方法,执行Runnable
然后调用finalCall()
。
实际工作可以作为专用的Runnable
实例,lambdas或方法引用传递 - 后者显示在这里:
public class RepeatedMethodContents
{
public static void main(String[] args)
{
RepeatedMethodContents r = new RepeatedMethodContents();
r.callWrapped(r::doSomething);
r.callWrapped(r::doSomethingDifferent);
}
private void callWrapped(Runnable runnable)
{
iniCall();
runnable.run();
finalCall();
}
private void doSomething()
{
System.out.println("doSomething");
}
private void doSomethingDifferent()
{
System.out.println("doSomethingDifferent");
}
private void iniCall()
{
System.out.println("ini");
}
private void finalCall()
{
System.out.println("final");
}
}
根据需要输出:
ini
doSomething
final
ini
doSomethingDifferent
final
顺便说一句:对于像这样的事情,我总是犹豫是否使用反射 。大多数情况下,有一种更简单,更直接,更不容易出错的方式。
答案 3 :(得分:0)
在Java中,您不能将方法作为参数传递。您可以通过Runnable
传递:
public void method1() {
call(new Runnable() {
@Override
public void run() {
//do something
}
});
}
public void method2() {
call(new Runnable() {
@Override
public void run() {
//do something different
}
});
}
public void call(Runnable runnable){
iniCall();
runnable.run();
finalCall();
}
但是,我真的不喜欢这种方法。我认为你可以应用模板设计模式。
答案 4 :(得分:0)
我不确定我是否喜欢在其他人使用过的情况下使用Runnable
。通常,我认为Runnable
是在线程,执行程序服务等中运行的东西。并且支持the documentation:
Runnable接口应该由任何其实例都要由线程执行的类实现。
但是从头开始做同样的事情真的很简单快捷。我们可以创建一个抽象类来保存您需要的结构:
public abstract class AbstractClass
{
private void iniCall() { ... } // Could also be abstract
private void finalCall() { ... } // Could also be abstract
public void doTheThing()
{
iniCall();
foo();
finalCall();
}
public abstract void foo();
}
当然,你需要提出更好的名字,但这是起点。然后我们有两个选择:实例化通过扩展此类构建的匿名类,或创建一个新的具体类。以下是使用匿名类的示例:
AbstractClass a = new AbstractClass()
{
@Override
public void foo()
{
// Place an implementation here.
method(); // one example, based on the OP.
}
};
a.doTheThing();
以下是你如何做一个实际的课程:
public class ConcreteClass extends AbstractClass
{
@Override
public void foo()
{
// Place an implementation here.
}
}
ConcreteClass c = new ConcreteClass();
c.doTheThing();
我主要想提出这个问题,以便你可以看看'匿名类'范例,这类似于能够将函数作为参数传递。其他语言有指向函数,委托等的指针 - 这就是Java所具有的。编译器将确保您的匿名类和具体类将具有foo
的实现,否则它将无法编译,因此您不能只是去'oops'并忘记实现。