We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Okay, on with my little project...
In the following clipped piece of code, I would like to make the HashMap a class variable, because the values stored in it never change and there's no reason for each instance to have its own.
class Cement {
private HashMap<String, Pigment> chart;
Cement() {
chart = new HashMap<String, Pigment>();
chart.put("GN", new Pigment("GN", 137));
chart.put("2R", new Pigment("2R", 143));
chart.put("8G", new Pigment("8G", 255));
}
}
class Pigment {
private String name; // name
private int v; // value
Pigment(String t_name, int t_v) {
name = t_name;
v = t_v;
}
}
I've tried with a static initializer static{}
class Cement {
private static HashMap<String, Pigment> chart;
static {
chart = new HashMap<String, Pigment>();
chart.put("GN", new Pigment("GN", 137));
chart.put("2R", new Pigment("2R", 143));
chart.put("8G", new Pigment("8G", 255));
}
Cement() {
}
}
class Pigment {
private String name; // name
private int v; // value
Pigment(String t_name, int t_v) {
name = t_name;
v = t_v;
}
}
I get error:
Cannot define static initializer in inner type xxx.xxx
Then I found information about nested classes and the fact you need an enclosing class to use static... I'm a bit lost here. --> Is it possible to make this HashMap a class variable? --> I didn't know my class Pigment was nested... is it?
Answers
yes. the preprocessor throws a class around your entire sketch making all your classes inner classes.
the way around this, iirc, is to move the class to a new file with a .java extension.
1st of all, some essential introduction to the subject: :-B
Processing's pre-processor gathers all ".pde" tabs together and wraps 'em all up as 1 top class!
Therefore our own classes & interfaces there become nested to that PApplet "sketch mega class"!
There are 3 types of nested classes:
Conventionally in the Java world, anonymous class instantiation is the only type considered by programmers!
Inner classes are mostly a Processing thing aFaIK. And static nested classes are even a rarer sight anywhere!
I believe you meant to have around a shareable & somewhat "immutable" data container, right?
It's a wise choice avoid wasting RAM unnecessarily btW. =D> However you've got some obstacles ahead! :-SS
Neither an inner class nor an anonymous instance can have anything
static
within them.W/ notorious rule exception for primitive & String constant fields w/ known compile-time values! L-)
Also, static methods & initializer blocks are restricted to access other static members only!
Only non-static methods & initializer blocks can access both static & non-static members!
Next post I'm gonna discuss some solutions for that seeming impasse! O:-)
Let's consider @koogs' proposal:
A separate ".java" tab would allow us to have top classes in it.
A regular top class is the opposite of a nested 1. And can have both static & non-static members! \m/
It is indeed the logical solution for Java's point-of-view. However, not so much for Processing's! Here's why: @-)
In short, we should stick w/ nested classes in order to preserve some Processing familiarity.
Coming next round some workarounds to access static members inside non-static classes! o->
I disagree with GoToLoop's conclusion. .java tabs are OK, in some cases.
The class shown above doesn't use any Processing specific features, so it is a perfect candidate to put in a .java file.
It's self-evident ".java" tabs are outside Processing's approach of turning everything into a PApplet class! :O)
That was a smart move, since we can directly access the whole Processing's API w/o an explicitly reference!
That is exactly what made a Java-based Processing palatable for its main target audience! (*)
@Moxl is looking for some way to have static fields in nested classes. Which is by itself an advanced topic!
Since nested classes are virtually unknown in the Java world, few folks know static members can have issues!
Even fewer know that regular top classes are implicitly static.
And that's why we can freely have both static & non-static members in them!
So how can we include static members in an inner class after all? The solution is as simple as making an inner class inherit static members from another static class or interface! And here's a recent case: *-:)
In this thread: http://forum.processing.org/two/discussion/6838/1d-array-affecting-2d-array
Hosted online: http://studio.processingtogether.com/sp/pad/export/ro.91FXxn8BG2fPL/latest
There's a class there called Box that includes 2 fields for defining its rect()'s dimensions.
Their values depend on non-static canvas' width & height. So I couldn't declare them
static final
!Problem is that even though all Box objects would have the exact same dimensions, 2 unnecessary dx & dy fields would be instantiated for each 1 in the process! While 1 shareable pair would be just enough!
But since Box is an inner class (non-static), we can't implement
static
members in it.Unless they're primitive or String constants as I've already mentioned before!
In order to fix that, I've implemented a separate static nested class called BoxData,
placed those dx & dy as static fields there, and made Box extend it: \m/
Now Box objects can access dx & dy fields, while only 1 copy of them exists. Problem solved! <):)
No need for complicated separate ".java" tabs at all! :))
Having a look at your 2 classes: Cement & Pigment, they don't make much sense.
Why having the same String key in the HashMap repeated as a field for the Pigment class?
chart.put("GN", new Pigment("GN", 137));
It seems like you're trying to make Pigment imitate a Map data container somehow!? :-??
I'll consider that you merely wanted to inherit a HashMap object referenced by a static field, right?
Following the same static nested class technique I did before, I've made a static abstract class called Chart
in order to contain only 1 HashMap instance. And a non-static inner class called Pigment to extend Chart's members:
And an alternative option using an IntDict inside an
interface
:In order to fix that, I've implemented a separate static nested class called BoxData, placed those dx & dy as static fields there, and made Box extend it
Yes! Thanks @GoToLoop, that's what I'll use, I guess. But then, in your first BoxData example, how is it that declaring BoxData as abstact make it possible to declare class variables in class Box?
Why having the same String key in the HashMap repeated as a field to the Pigment class?
Well observed, I thought about that after posting. Actually, the Pigment object contains more instance variables, which I just omitted for the snippet. Probably not a winning formatting choice for the post, too...
It's completely unrelated. It just needs to be
static
! You can freely remove that if you wish so. ;))Just declared it
abstract
as a hint that it's not supposed to be instantiated. Rather inherited from another class!Both dx & dy
static fields
weren't declared insideinner class
Box; rather instatic class
BoxData.Inner class
Box merely inherited fromstatic nested class
BoxData's members! :-BHah! Is this a nice trick or what?! Thanks.
PS: unrelated, maybe someone could PM, but how do I include emoticons in posts? Do I need to write HTML?
There's a smiley button at the far top right in this very typing box! <:-P
Oh right. I had this script blocker running, maybe that's the reason I couldn't see the button... :)
I believe you meant to have around a shareable & somewhat "immutable" data container, right?
By the way, yes, you totally got what I meant. Sorry for lacking vocabulary...