如何创建一个无法通过构造函数执行的函数?

huangapple go评论70阅读模式
英文:

How to create a function that cannot be executed by a constructor?

问题

public abstract class A {
    public A () {
        // 在这里做一些事情 :)
    }
    
    public abstract void doStuff();
    
    public final void addToArray() {
        if(isCalledFromConstructor/*在这里帮我*/)
            throw new RuntimeException("不能在构造函数中执行 addToArray 函数");
        if(!AS.contains(this)) AS.add(this);
    }
    
    private static final java.util.Set<A> AS = new java.util.concurrent.ConcurrentSkipListSet<A>();
    
    public static final class B extends A {
        public B(){
            addToArray();//在这里抛出一个错误
        }
        
        @Override
        public void doStuff(){
            System.out.println("正在做事情");
        }
    }
}
英文:

Say I have function x which is a function in an abstract class. x adds itself to a private arraylist if it does not already contain it. I want to make a function that cannot be executed inside the constructor so that 'x' cannot be added to the arraylist if the constructor errors, and can only be called after the constructor(s) has finished. The gist of my situation is that I want the set to be private so only the class A can access it, nothing should ever be removed from the list if it is added, the addToArray function should only ever need to happen once and should never happen from the constructor. The constructor would only matter if it is a subclass' constructor.

public abstract class A {
    public A () {
        //do stuff :)
    }
    public abstract void doStuff();
    public final void addToArray() {
        if(isCalledFromConstructor/*HELP ME HERE*/)
            throw new RuntimeException(&quot;Cannot execute addToArray function from a constructor&quot;);
        if(!AS.contains(this))AS.add(this);
    }
    private static final java.util.Set&lt;A&gt; AS = new java.util.concurrent.ConcurrentSkipListSet&lt;A&gt;();
    public static final class B extends A {
        public B(){
            addToArray();//THROW AN ERROR HERE
        }
        @Override
        public void doStuff(){
            System.out.println(&quot;Doing stuff&quot;);
        }
    }
}

答案1

得分: 1

有了更多关于您试图实现的背景信息,我可能能够更好地提供关于实现您最终目标的建议。话虽如此,如果您绝对确定要做您所询问的事情,一种方法是从 addToArray 中调用

Thread.currentThread().getStackTrace()

并检查堆栈跟踪的内容,以查看当前是否在构造函数内部。

特别地,这段代码

  boolean isCalledFromConstructor() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    for (StackTraceElement stackTraceElement : stackTrace) {
      String methodName = stackTraceElement.getMethodName();
      if (methodName.equals("<<init>>")) return true;
    }
    return false;
  }

应该可以为您做到这一点,尽管这不是我最喜欢的代码片段 如何创建一个无法通过构造函数执行的函数?

正如其他人已经评论的那样,这样做可能是设计上的疏忽的迹象。如果可能,请提供有关整体目标的更多细节。

英文:

With more context on what you’re trying to accomplish, I might be able to give a better suggestion on achieving your ultimate goal. That said, if you are absolutely set on doing what you are asking, one way is to call

Thread.currentThread().getStackTrace()

from within addToArray and examine the contents of the stack trace to see if you’re currently inside of a constructor.

In particular this

  boolean isCalledFromConstructor() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    for (StackTraceElement stackTraceElement : stackTrace) {
      String methodName = stackTraceElement.getMethodName();
      if (methodName.equals(&quot;&lt;init&gt;&quot;)) return true;
    }
    return false;
  }

should do it for you, although it's not my favorite bit of code 如何创建一个无法通过构造函数执行的函数?

As other people have commented, doing this may be a sign of a design oversight. Please give more details on the big picture goal if you can.

答案2

得分: 0

你可以拥有一个名为 boolean isInitialized 的私有变量,并在构造函数中将其设置为true。在add方法中,检查这个值是否为 false,如果是,则抛出错误。

如果您的环境允许,您可以使用 @PostConstruct 方法注解来安全地将其添加到列表中。

但我还建议检查您的代码设计。您正在将一个实例添加到一个不是线程安全的私有静态列表中。

英文:

You could have a private variable like boolean isInitialized and set this to true in constructor. In the add method check if this value is false and throw error.

If your environment allows it you could use @PostConstruct method annotation to add it to your list safely.

But i also recommend to check your code design. You are adding an instance to a private static list that is not thread safe.

huangapple
  • 本文由 发表于 2020年10月23日 08:31:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/64492321.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定