Sorry for the vague title; I'm not entirely sure what the problem is.
Background
In short: child classes of a certain base class must define 3 specific static methods, hiding the base class' static methods. An implementation description class checks this on initialization. Seemingly at random when running the application, however, I get run time exceptions during initialization saying that I haven't properly reimplemented the methods. But I am working in unrelated classes elsewhere when this happens, as rarely as it does, and simply shuffling the order of the methods fixes it for another long while.
Code
So, three classes: The Base, the Derived, and the AlgImplementation class:
AlgImplementation constructor:
/* verifying that the extending class has implemented these methods */
if (this.getAlgorithmClassName() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassName() method from as specified.");
}
if (this.getAlgorithmClassDescription() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassDescription() method from as specified.");
}
if (this.getAlgorithmClassAnalyticLevel() == null) {
throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassAnalyticLevel() method from as specified.");
}
That's where the problem happens, one of those checks fails. I get the IllegalArgumentException from one or more of the above. I can simply move the order of the implementation around in the derived class, to force a rebuild of that code, and then it works fine.
Base & Derived classes both have the same simple static methods, but the static fields they return are defined differently:
class Derived extends Base {
public static AnalyticLevel getAlgorithmClassAnalyticLevel()
{
return ANALYTIC_LEVEL;
}
public static String getAlgorithmClassName()
{
return NAME;
}
public static String getAlgorithmClassDescription()
{
return DESCRIPTION;
}
}
The above fields are all non-null static final Strings.
Now, in the Derived class I declare a static final AlgImplementation field:
public static final AlgImplementation derivedAlg = new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
Finally, the last thing I think you will need to know is that that this AlgImplementation instance does the this for each static method class:
public String getAlgorithmClassName() {
String className = "";
try {
className = (String)algorithmClass.getDeclaredMethod("getAlgorithmClassName", new Class<?>[0]).invoke(null, new Object[0]);
} catch (Exception e) {
throw new UnsupportedOperationException("Required static method getAlgorithmClassName() not implemented on "+this.getClass().getName());
}
return className;
}
Finally
So, my question is: How can the check for the derived methods fail if these methods are in fact declared? Is there an issue with declaring a static AlgImplementation field that refers to the very class it is defined in (causing some weird order of compilation issue, or something like that)?
The error is during initialization of Derived class, specifically at the line initializing the static AlgImplementation field, which is why I think there might be a problem with doing that in the Derived class itself.
I suspect the problem is due to initialization order of the static final fields of the classes. By using reflection during class initialization, you're accessing the class before it has fully initialized. If on a derived class, you have the following:
public static final String NAME;
static {
NAME = "some name";
}
public static final AlgImplementation derivedAlg =
new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
then AlgImplementation will check the NAME constant after it has been initialized, and will read the "some name" string. If you reverse the order:
public static final AlgImplementation derivedAlg =
new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");
public static final String NAME;
static {
NAME = "some name";
}
then AlgImplementation will read the constant before it has been assigned, and will read null instead.
I'm not sure if it's possible for this to happen if the NAME is assigned directly by a compile-time constant like this:
public static final String NAME = "some name";
I would have guessed that would prevent the problem, but maybe not. Your statement that "shuffling the order of the methods fixes it for another long while" supports the idea that the problem is due to initialization order. I'd suggest moving the derivedAlg field after all the other constants to encourage it to be initialized last.
Static methods do not participate in class hierarchy. You should always use either staticMethod() or Class.staticMethod() instead.
Related
I am new to Java and am wondering how to create in an elegant way a global object whose members are constant. One way to do this is:
public class Global {
public final static String NAME = "John Doe";
public final static int AGE = 100;
}
and then calling it outside as
import Global;
public static void main(String[] args) {
int age = Global.AGE; // works fine; age cannot be modified
}
The only issue is: I have a lot of variables in this class that I'm copying from a text file and adding the keywords "static", "public", and "final" is cumbersome and makes it look ugly. I know it's not a big issue, but I would like a more elegant solution to this. Any ideas? I have tried nested classes but could not figure out to have it behave correctly.
If you are sure that you will handle only constants you can declare your class as final class and define a private constructor - Doing that, you avoid instantiation (the assertion error will make the class safe even if they try to instantiate the class using reflection), this is an elegant way to consolidate your constants in a class.
public final class Global {
public static final String NAME = "John Doe";
public static final int AGE = 100;
}
private Global() {
//this prevents even the native class from
//calling this constructor as well :
throw new AssertionError();
}
Advantages:
Since the required static memebers are imported statically, the class namespace is not polluted.
The compiled code has one fewer binary compatibility constraint (that “class implements Constants Interface”).
Because static imports apply only to the current file (and not the whole class hierarchy), it is easier to discover where each static member is declared.
Run-time and compile-time semantics are more closely aligned when using static imports instead of constants interfaces.
If required, static blocks can be declared.
Since some answers are suggesting using the interface, I suggest you check out this article Why the Constant Interface Pattern Should Be Discouraged. If you can check out the Effective Java book will be a good reference as well.
You can use interface also
public interface Global {
String NAME = "John Doe";
int AGE = 100;
}
This answer says that we can't instantiate more than one object at a time via private constructors. I have modified the code which does just the opposite:
class RunDatabase{
public static void main(String[] args){
Database db = Database.getInstance("hello");//Only one object can be instantiated at a time
System.out.println(db.getName());
Database db1 = Database.getInstance("helloDKVBAKHVBIVHAEFIHB");
System.out.println(db1.getName());
}
}
class Database {
//private static Database singleObject;
private int record;
private String name;
private Database(String n) {
name = n;
record = 0;
}
public static synchronized Database getInstance(String n) {
/*if (singleObject == null) {
Database singleObject = new Database(n);
}
return singleObject;*/
return new Database(n);
}
public void doSomething() {
System.out.println("Hello StackOverflow.");
}
public String getName() {
return name;
}
}
And as expected both the strings are being printed. Did I miss something?
We can't instantiate more than one object at a time via private constructors.
No, we can. A private constructor only avoids instance creation outside the class. Therefore, you are responsible for deciding in which cases a new object should be created.
And as expected both the strings are being printed. Did I miss something?
You are creating a new instance every time the getInstance method is called. But your commented code contains a standard lazy initialization implementation of the singleton pattern. Uncomment these parts to see the difference.
Other singleton implementations you can look over here.
Private constructors are used to stop other classes from creating an object of the "Class" which contains the private constructor.
This is done to provide the singleton pattern where only a single instance of the class is used.
The code that you have mentioned is supposed to create just one instance of the class and use that instance only to perform all the operations of that class. But you have modified the code which violates the singleton design pattern.
Why do we need a private constructor at all?
Basically 3 reasons:
if you don't want the user of the class creates an object directly, and instead use builders or similars,
if you have a class defined for constants only, then you need to seal the class so the JVM don't create instances of the class for you at runtime.
singletons
I have some code that I need to reuse in several Java apps. That code implements a GUI which in turn needs to access some static variables and methods from the calling class. Those variables and methods are always called the same in all of the apps. Is there a generic way to obtain a handle to the calling class in Java so the code for "someGUI" class can remain untouched and in fact come from the same source file for all the different apps?
Minimal working example:
import javax.swing.*;
class test {
static int variable = 123;
public static void main(String[] args) {
someGUI sg = new someGUI();
sg.setVisible(true);
}
}
class someGUI extends JFrame {
public someGUI() {
System.out.println(String.format("test.variable = %d", test.variable));
}
}
How can I "generify" the reference to "test" in test.variable to always just refer to the calling class? It's not the "super" class, at least using super.variable doesn't work.
Firstly I would advise against this approach since there are only brittle ways to implement it. You should parameterize SomeGUI with a parameter containing the values you need instead.
However, it is possible to do what you ask by examining the thread's stack trace and using reflection to access the static fields by name. For example like this:
class Test {
static int variable = 123;
public static void main(String[] args) throws Exception {
SomeGUI sg = new SomeGUI();
}
static class SomeGUI extends JFrame {
public SomeGUI() throws Exception {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
// stackTrace[0] is getStackTrace(), stackTrace[1] is SomeGUI(),
// stackTrace[2] is the point where our object is constructed.
StackTraceElement callingStackTraceElement = stackTrace[2];
String className = callingStackTraceElement.getClassName();
Class<?> c = Class.forName(className);
Field declaredField = c.getDeclaredField("variable");
Object value = declaredField.get(null);
System.out.println(String.format("test.variable = %d", value));
}
}
}
This will print test.variable = 123.
Obviously this is sensitive to renaming of the variables. It is also sensitive to dynamic proxies.
Also, it should be noted that you need to do this in the constructor. If you try to do this kind of lookup in other methods you can not find out how the instance was created.
There is no inheritance between somGUI and test,
Actual inheritance is there between someGUI and JFrame.
If you use super(), JVM tries to find 'variable' in JFrame, that is not what you wanted.
Use static methods setters & getters to access the 'variable' instead of direct accessing them.
In Java we can do the following to initialize class and call method inside that class:
public class MyClass {
public String myClassMethod() {
return "MyClass";
}
}
.
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass(); // initialize MyClass
myClass.myClassMethod();// call a method
}
}
If my class is an enum class, implementation will be the following:
public enum MyEnumClass {
INSTANCE;
public String myEnumClassMethod() {
return "MyEnumClass";
}
}
.
public class Test {
public static void main(String[] args) {
MyEnumClass myEnumClass = MyEnumClass.INSTANCE;
myEnumClass.myEnumClassMethod();
}
}
Both of these cases works in the same way, but it is said to be better in the enum implementation. My question is why and how it is happening?
An enum is essentially a singleton pattern.
The JVM handles the initialization and storage of enum instances. To see this most clearly you can write:
public enum MyEnumClass {
INSTANCE("some value for the string.");
private final String someString;
private MyEnumClass(final String someString) {
this.someString = someString;
}
public String getSomeString(){
return someString;
}
}
And in another class:
public static void main(String[] args) {
final MyEnumClass myEnumClass = MyEnumClass.INSTANCE;
system.out.println(myEnumClass.getSomeString());
}
This would print out "some value for the string.".
This demonstrates that the enum instances are initialised at class load time, i.e. as if by the static initialiser.
Or put another way:
new MyClass() == new MyClass();
Is always false, whereas:
MyEnumClass.INSTANCE == MyEnumClass.INSTANCE;
Is always true. i.e. MyEnumClass.INSTANCE is always the same MyEnumClass.INSTANCE whereas a new MyClass is created every time your call new MyClass().
This brings us nicely to your question of "better".
An enum is a singleton instance with various nifty methods for converting String enum names into a reference to the singleton instance that it represents. It also guarantees that if you de-serialize an enum there won't be two separate instances like there would for a normal class.
So an enum is certainly much better as a robust and threadsafe singleton than a class.
But we cannot have two instances of INSTANCE with the different values for someString so the enum is useless as a class...
In short enums are good for what they're good for and classes are good for what they're good for. They are not substitutes and therefore cannot be compared in any meaningful way expect when one is used as the other.
It's a simple implementation of the Singleton pattern, relying on the mechanisms of how Enum's work.
If you use MyEnumClass.INSTANCE a second time, you'll get the same object instance.
In contrast, new MyClass(); will create a new object.
See also discussion here:
What is the best approach for using an Enum as a singleton in Java?
There would possibly be more to learn by reading Java Language Spec Section 8-9
Right now I'm thinking about adding a private constructor to a class that only holds some String constants.
public class MyStrings {
// I want to add this:
private MyString() {}
public static final String ONE = "something";
public static final String TWO = "another";
...
}
Is there any performance or memory overhead if I add a private constructor to this class to prevent someone to instantiate it?
Do you think it's necessary at all or that private constructors for this purpose are a waste of time and code clutter?
UPDATE
I'm going for a final class with private constructor and a descriptive javadoc for the class. I can't use a ENUM (which I'd prefer) because I'm stuck on Java 1.4 for now. This would be my modification:
/**
* Only for static access, do not instantiate this class.
*/
public final class MyStrings {
private MyString() {}
public static final String ONE = "something";
public static final String TWO = "another";
...
}
Use of private constructor to prevent instantiation of class?
There are several ways you can think of users preventing from the Instantiations for the purpose of creating the Constants
As you have mentioned a class with the private Constructors and has all the string constants, is one way, even there is an overhead, that can be negligible
Else you can create a Class with Final Modifier and Define your string constants
You can use the Abstract Class with the String Constants
You can define the string constants in the properties files and can access from that, this will definitely reduce the memory and increase the flexibility of your code.
For me the best explanation is in Effective Java book: Item 4: Enforce noninstantiability with a private constructor (See more)
In Summary:
Private constructor is due utility classes were not designed to be instantiated, so is a design decision. (NO performance or memory overhead)
Making a class abstract doesn't work because can be subclassed and then instantiated.
With an abstract class the user may think the class is for inheritance.
The only way to ensure no instantiation is to add a private constructor which ensures the default constructor is not generated.
Private constructor prevents inheritance because the super constructor cannot be called (so it is not need the declare the class as final)
Throw an error in the private constructor avoids call it within the class.
Definetively, the best way would be something like next:
public class MyStrings {
private MyStrings () {
throw new AssertionError();
}
...
}
You could add a private constructor, but there are two other options.
In the same situation I would use an enumerator. If it makes sense to your implementation, you could use that instead, if it's public or private depends on where you need to use it:
public enum MyStrings {
ONE ("something"),
TWO ("something else");
private String value;
private MyStrings(String str) {
this.value = str;
}
}
Another option would be to put it in an abstract class, those can not be instantiated:
public abstract MyStrings {
public static final String STUFF = "stuff";
public static final String OTHER = "other stuff";
}
Access for both enumerator and abstract class works just like with the implementation you presented:
MyStrings.STUFF
If you don't won't anyone to make an object of the class you could make it abstract like this
public abstract class MyStrings {
public static final String ONE = "something";
public static final String TWO = "another";
}
and access your static variables like this
String val1 = MyStrings.ONE;
String val2 = MyStrings.TWO;
I think this would be a nicer solution.
I would rather use an enum to hold that Strings. This would ensure that wherever you use that Strings, you only get passed in one of the allowed Strings.
There is no performance or memory overhead if you add a private constructor in this case. As well, it is not needed since your public static variables are shared among all instances of your object.
If your class has only static members, then there is no need to have a private or public constructor. All members are accessible even without an object. In fact I find it confusing to have a constructor in such a case.
A synthetic public constructor would have been generated any way. So no.
Really a few bytes out of hundreds of millions at runtime isn't going to make much difference.
I also suggest making the class final and just for completeness have the constructor throw an exception.
If you want terse source code, you could create an enum with no values. Might cause some confusion with beginner programmers though.
That's the right way to store some constants, as also suggested in Effective Java (2nd Ed.), item 19.