我在Android Java项目中调用过两次方法,但我想只调用一次。当我第二次调用该方法时,我想检查该方法是否已被调用。代码是这样的:
class SomeClass {
//called with certain condition
private void a(){
c(); //first call
}
private void b() {
c(); //second call,check here whether function is invoked already or not,if invoked not invoke here or vice-versa
}
//called with certain condition
private void c() {
}
}
答案 0 :(得分:4)
您必须使用布尔值(或计数器)来记录该方法是否已被调用。但是你如何做到这一点取决于正是你想要计算/限制的东西。
以下假定您使用计数器:
如果要计算所有上下文中对方法的所有调用:
private static int nos_calls;
public void function c() {
nos_calls += 1;
// do the call
}
如果您只想计算给定对象的方法调用,那么:
private int nos_calls;
public void function c() {
nos_calls += 1;
// do the call
}
如果您希望阻止多次调用该方法:
private int nos_calls;
public void function c() {
if (nos_calls++ == 0) {
// do the call
}
}
如果可以从不同的线程调用该方法,那么您需要以正确同步的方式进行计数; e.g。
private AtomicInteger nos_calls = new AtomicInteger();
public void function c() {
if (nos_calls.incrementAndGet() == 1) {
// do the call
}
}
等等。
答案 1 :(得分:1)
您可以这样做:
class A{
static boolean calledBefore = false;
public void a(){
....
c();
}
public void b(){
....
c();
}
public void c(){
if(!calledBefore){
//This will be executed if c() is not called before
//Do magic here
calledBefore = true;
}
}
}
如果您想拥有多个A类实例并且允许每个实例调用calledBefore
一次,那么 c()
应该是非静态的。
答案 2 :(得分:1)
如果要在程序的整个运行时只运行一次,请使用类静态变量。如果要为每个对象运行一次,请添加一个对象成员变量
class RunOnce {
private static boolean methodAHasRunOnce = false;
private boolean methodBHasRun = false;
public void methodA() {
if(RunOnce.methodAHasRunOnce) { return; }
System.out.println("Hello from methodA!");
RunOnce.methodAHasRunOnce = true;
}
public void methodB() {
if(this.methodBHasRun) { return; }
System.out.println("Hello from methodB!");
this.methodBHasRun = true;
}
}
现在运行:
RunOnce one = new RunOnce();
RunOnce two = new RunOnce();
one.methodA(); // Output: Hello from methodA!
one.methodB(); // Output: Hello from methodB!
one.methodA(); // No output
one.methodB(); // No output
two.methodA(); // No output
two.methodB(); // Output: Hello from methodB!
two.methodA(); // No output
two.methodB(); // No output
答案 3 :(得分:1)
我在这里看到2个解决方案:
public Clazz {
//private static boolean check = false; // if you want your method to be run once per class
private boolean check = false; // if you want your method to be run once per class instance
public void c() {
if(check) {
return;
}
check = true;
....
}
但你必须有一个接口:
public class TestInvocationHandler implements InvocationHandler {
//private static boolean check = false;
private boolean check = false;
private Object yourObject;
public TestInvocationHandler(Object object) {
yourObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(check) {
return null; // or whatever you need
}
check = true;
return method.invoke(yourObject, args);
}
}
然后你会像这样创建你的对象:
ObjectInterface i = (ObjectInterface) Proxy.newProxyInstance(ObjectInterface.class.getClassLoader(),
new Class<?>[] {ObjectInterface .class},
new TestInvocationHandler(new MyImplementingClass()));
答案 4 :(得分:0)
您可以向包含在函数中修改的函数的类中添加静态字段(例如,仅对其进行修改)以跟踪调用。
答案 5 :(得分:0)
方面将是这个问题的一般解决方案。我绝对不是一个专家(这个例子还没有经过测试),但它会像:
@Aspect
public class CallOnlyOnceAspect {
@Pointcut("call(* methodThatShouldBeInvokedOnlyOnce(..))")
void methodThatShouldBeInvokedOnlyOnce() {}
@Around("methodThatShouldBeInvokedOnlyOnce()")
public Object preventMultipleCalls(ProceedingJoinPoint thisJoinPoint) {
// You need to implement this method for your particular methods/counters
if (hasAlreadyExecuted(thisJoinPoint)) {
return null;
// or equivalent return value,
// e.g. you may have cached the previous return value
}
Object result = thisJoinPoint.proceed();
// Maybe cache result against thisJoinPoint
return result;
}
}
在这些地方可以找到更多细节: