英文:
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("Cannot execute addToArray function from a constructor");
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();//THROW AN ERROR HERE
}
@Override
public void doStuff(){
System.out.println("Doing stuff");
}
}
}
答案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("<init>")) 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论