Accessing static object without creating an instance of the class containing it - java

I'm having problem understanding "static". I have created class "pizzaMenu" containing ArrayList which contains pizzas. All pizzas are added within that class, and it shouldn't be modified later. But I want to access data about pizzas.
Everything is working properly, but I have to create object of "pizzaMenu" in "main" to make it work.
How can I properly initiate such instances, so I have access to them? But the initiation won't be visible in "main"? I'd like to keep "main" as clean as possible.

but I have to create object of "pizzaMenu" in "main" to make it work.
Yes, you need an instance of new PizzaMenu() in order to access that menu's items.
I'm having problem understanding "static".
Nothing in PizzaMenu should really be static (other than main, if you have it there). But, it basically mean it belongs to the class, and not any one instance of that class.
In other words, if you did make the list of pizzas static, then that says that all menus have the same pizzas, which shouldn't be true, right? Different places have different menus.
Here's an example.
public class PizzaMenu {
private List<String> pizzas = new ArrayList<>();
public void add(String name) {
pizzas.add(name);
}
public List<String> getPizzas() {
return pizzas;
}
// You can also move this to another class
public static void main() {
PizzaMenu menu = new PizzaMenu();
menu.add("Cheese");
for (String pizza : menu.getPizzas()) {
System.out.println(pizza);
}
}
}
All pizzas are added within that class, and it shouldn't be modified later.
You can use this, for example
private final List<String> pizzas = Arrays.asList("Cheese", "Pepperoni");
But, again, I think different instances of menus should have different pizzas.

You can declare pizzas as public static within pizzamenu.
public final static List<pizza> pizzas;
So you can access the pizza using
PizzaMenu.pizzas.
Also you mentioned
I'd like to keep "main" as clean as possible.
I think your concept about clean code is not fully correct.

Related

Creating auto initialized static objects in Java

I'm trying to create a subclass which auto creates itself. I defined Base which holds a list of instances. Then I defined Derived with a static member reg. reg is in place initialized by calling Base.Register(), which adds it to the instances list.
In the main() I'm printing the instances list of Base. But there is no initialization and I get an error - the instances list is null.
In a further attempt, I added a list of Booleans to Base. Whenever I register an instance, I'm changing this list. I also print this list in the program. I expected it to force the execution of the Base.register(), but to no avail.
I did find a solution that worked, but I don't appreciate - I could print the result of the Base.register() as saved in the Derived. That would force the static initialization. However, I intend to use the solution for a bunch of derived classes, and I wouldn't want to have to call each derived class directly.
Is there a way to force the static init?
I guess I could use reflections, I'm trying to avoid that at the moment.
EDIT what I am actually trying to do, is to build a set of derived classes (for unit testing). All classes derive Base. I want to avoid the need to create instances separately for each. I'm trying to get a generic solution, in each derived class code (only). Such a solution would be easy to copy & paste.
public class StaticTest {
private static class Base{
private static ArrayList<Base> _instances = null;
private static ArrayList<Boolean> _regs = null;
public static int _count = 0;
public static void init(){
_regs = new ArrayList<>();
for (int i=0;i<10;i++)
_regs.add(false);
}
protected static boolean register(Base b)
{
if (_instances == null)
_instances = new ArrayList<>();
_regs.set(_count++, true);
return _instances.add(b);
}
public static void printAll(){
for (Boolean b: _regs)
System.out.printf("hello %s%n", b.toString());
for (Base b: _instances)
System.out.printf("hello %s%n", b.toString());
}
}
private static class Derived extends Base{
public static boolean _reg = Base.register(new Derived());
}
public static void main(String[] args) {
//System.out.print(Derived._reg ? "0" : "1");
Base.init();
System.out.printf("Base._count = %d%n",Base._count);
Base.printAll();
}
}
Short answer is that static initialization occurs only when a class is first used. When you invoke Base.init(), Derived hasn't been yet used and so register hasn't been called.
Medium answer is that if you uncomment the line System.out, you get a NullPointerException because the static code in Derived calls to register before init initializes the Arraylist. Moving the init to the first line solves it and it works as you wanted.
Final answer, if you're trying to understand how a Java classes initializes and it's limitations, it's ok, but the mechanism you're trying to write is a very bad design. Please provide the real problem you're trying to solve and someone can point you in the right direction.

Is there any purpose to make private class variable to public

Hello I am curious to know that Is there any purpose to make private class variable to public in Java.
public class XYZ {
public String ID;
public ABC abc;
private class ABC {
public boolean isExist;
}
}
Thanks in advance.
Yes, there's a purpose. If you do that then those program elements which can access the class can manipulate that variable directly. Otherwise (say if the variable is private), those elements would still be able to access the class but won't be able to manipulate the variable (unless you provide a getter/setter for it).
Think about it this way: the class modifier defines the level of access to the class, the variable modifier then defines the level of access to the variable itself (for those elements which can access the class).
This is sometimes done for data-only classes. For example, this is sometimes done to represent the models stored in databases (see Objectify for a real example of how this is used, in conjunction with annotations, to represent the database models that are stored in an App Engine database).
That being said, this sort of thing makes for a very poor API. If you do this, I'd suggest doing it with classes that are either package-level access or in private nested classes, only. When exposing functionality or data to code outside your package, it is generally better to do it with a carefully designed interface that would allow you to change the implementation if your underlying structure were to change.
That is to make isExist visible to XYZ class.
Note, ABC is only visible to XYZ and not to any outside classes and its variable is public so you can have access to it. private has not meaning to XYZ, only outside classes
From inside XYZ,
ABC abc = new ABC(); //can only be accessed by XYZ.
abc.isExists = true; //can only be accessed by XYZ
Making isExist public means you do not care about encapsulating (prevent it from unwanted manipulation from outside) it. If you make it private, you will need a get accessor to expose it
private class ABC {
private boolean _isExist; //only through accessors
public boolean isExist()
{
return _isExist;
}
}
You can do either of the following two things to your class instance variables:
THING # 1: Keep your instance variables private. Then have public getter and setter methods to get and set the value of that variable. The good thing about it is that you get to put checks inside the setter method. For example, lengths can never be negative. So, you can't just make lengths public and let anyone assign it whatever value they want. You need to make sure the value being assigned to it is not negative. So:
class myClass {
private int length;
public void setLength(int i) {
if ( i > 0 ) {
length = i;
}
}
}
Also, you can make your instance variables read-only, write-only, or read-and-write, depending on the availability of getter and setter methods for that private variable.
THING # 2 : If you don't need any restrictions on the value of your instance variable, and you want it to neither be read-only nor write-only, then it's fine to keep that variable public. For example: babies can have any name - no restrictions:
class Baby {
public name;
}
class Mother {
public void nameTheBaby() {
Baby baby = new Baby();
baby.name = "Sarah";
}
}

Keeping track of all instances of a subclass in the superclass

I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.

Gaps in Java knowledge but can't find the direction to search

===================================================================================================
UPDATE:
My problem was that I did not know that classes can indeed communicate with each other. For example, you can create 2 classes, instantiate an object of each class in your program, and then actually pass one object into the other. This not only directly solved my problem, it opens an entire world of possibilities for the future.
public class FirstClass {
int valueToPass = 100;
void methodToPass(){
//do stuff
return;
}
}
public class SecondClass {
FirstClass passedInObject;
int valueFromOtherClass = passedObject.valueToPass;
return;
}
}
===================================================================================================
I understand a class is a blueprint of attributes and actions that can be instantiated as an object.
I understand an inner class is a non static class defined within another class and has access to the outer class' data.
I understand a child class is a separate file defining a class that does not have access to its parent's data.
So I've got my main activity class of an Android application. I'm just making a simple dice game to help tie up all the loose ends. I've defined the follow child classes in separate .java files:
Dice
ScoreCard
I instantiate an array of 5 Dice objects and 1 ScoreCard object and attach those objects to a "view" in the android OS's window, then assign an action method to that view with the set click listener method inside the object. The objects work flawlessly. I can click the dice and they will hold and unhold themselves, roll, and update their own views. I can of course access the value of the dice from my main class by referencing their object.value variable. (I understand that accessors are presumed by many to be superior to directly interacting directly with a child class' variables, this app is just to solidify conceptual ideas of the overall flow of an application) I can click a slot on the scoresheet and it will toggle the highlight that slot as the slot to assign the score to. The scorecard object also updates the entire scorecard on the screen after each interaction.
So far so good, everything is working great, and I understand everything that is going on.
However, in my main activity class, I now want to create a roll function, and assign that function to the click listener for the roll button. That works, however, when assigning a function to the click listener, you can not reference any non final variables because the click listener of a given view actually instantiates an anonymous object (anonymous class?) of the View class and overrides the onclick method with its own, therefore you can not reference any non final variables from an inner class defined in another method. In other words, you can't pass the function you assign to the click listener any values from your main class, and although I do not understand why, the roll function I created can not access the main class' variables directly.
There is the first gap in my knowledge, and I've read dozens of tutorials, watched dozen's of videos, but I don't know why my roll function can't see the variables.
public mainclass extends otherclass {
#override
otherclass.method {
// where my application starts
int a=7;
roll();
}
void roll(){
int funcVar = a;
return;
{
}
Eclipse says that a can not be resolved.
I try to make a public thinking that might allow the function to see it, but if I change
int a=7;
to
public int a=7;
then Eclipse says that it can't be public, only final.
A way around this is to create a new child class called Roll, or perhaps ActionButton to use it for other buttons in the future, just as I did with the ScoreCard and Dice classes. This works great, in so far as I can instantiate a roll button object, assign a view to the object and then set the click listener to one of the object's methods. However, this transfers the functionality of my rollbutton from my MainActivity class to my RollButton class, which doesn't have access to the data in my dice and scorecard objects. In other words, I can't figure out how to make my child classes talk to each other, I don't really think they are even supposed to. I imagine the main class is supposed to access each child class independently, but if that's the case then I'm not really sure what I'm supposed to do at this point.
The only solution I can think of is to put all those child classes into the same child class, DiceGame, and pretty much just use the MainActivity class to instantiate an object of the DiceGame class and transfer processing entirely over to that object. While that would work, all the methods in the class would have access to all the data in the class, it seems to contradict the entire purpose of object oriented programming.
Is this all so messed up because of the way the click listener in android apps is assigned through instantiating an anonymous inner class that can't access any non final variables, or I just missing a key concept in the way Java applications are structured?
I'm sorry this is so long, but I really couldn't shorten it and still convey the entire problem.
-------edit----------
public class MainActivity extends Activity {
public int a=7;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
// my application starts here
Dice[] gameDice = new Dice[6];
for (int i=1;i<6;i++) gameDice[i]= new Dice();
for (int i = 1; i<6 ; i++){
gameDice[i].dieView = (ImageView) findViewById(R.id.die1 + (i-1));
gameDice[i].setListener();
}
int[] slotId = new int[] {R.id.val1,
R.id.val1,R.id.val2,R.id.val3,R.id.val4,R.id.val5,
R.id.val6,R.id.valsubtotal,R.id.valbonus,
R.id.val3k,R.id.val4k,R.id.val5k,R.id.valfh,
R.id.valsmstr,R.id.valstr,R.id.valdicey,R.id.valtotal
};
ScoreCard scoreCard = new ScoreCard();
scoreCard.NUMBER_OF_SLOTS = slotId.length;
for (int i=1 ; i<scoreCard.NUMBER_OF_SLOTS ; i++){
scoreCard.slotView[i]=(TextView) findViewById(slotId[i]);
if (i!=8 && i!=15) scoreCard.setListener(i);
}
scoreCard.initScoreCard();
rollButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
roll();
}
});
}// end of overridden method
void roll(){
//do stuff
int funcVar = a; // can totally see a now that it is higher scope
return;
}
}//end of class
The suggestion to increase the scope of a did in fact work. However, a is just an example I was using for simplicity's sake. I really need to access those data contained in the objects I instantiated, and if I instantiate them in a higher scope the application abruptly ends upon launch.
Perhaps the confusion is between a variable and a field. A field is a property that is associated with an object. A variable exists only in the context of a method. When the method finishes, the variable vanishes.
A field, on the other hand, looks exactly the same as a variable except that a field is declared outside of any method, directly on the class "body". Fields and methods are declared at the same hierarchical level. You can see that on Eclipse. Check the "outline" view.
If you need several methods to read and write the same "variable", then what you need is a field. I hope this clarifies.
Variables can have different scopes:
public class MyClass {
static int a; // variable bound to class MyClass, seen from all instances
int b; // variable bound to instance, each instance of MyClass has its own value
public void foo(int c) { // parameter variable: local
int d; // local variable
}
}
Local variables in a method are visible only within the same method invocation (so each time foo() is invoked, new local variables are used).
Values can be passed indirectly by storing them in instance or class variables (global variables), but that's ugly and error prone. The better variant is to pass the values as method arguments, this works well with multiple invocations and also multiple Threads, and removes the side effects you'd have when passing values using global variables.
In your example, just pass the value of a to your method:
public mainclass extends otherclass {
#override
otherclass.method {
// where my application starts
int a=7;
roll(a);
}
void roll(int funcVar){
// funcVar is whatever value was passed, here: 7
return;
{
}

Calling a specific member of an object array from another class-method

I am now working on the AI section of my project. I am calling a method from my AI class which is intended to calculate where the Gladiator objects I have drawn need to actually end up. I passed to that method a List containing all my objects I want to place. A previous method from the AI class has determined where they want to be from each other, distance-wise and I have stored it as gladiator[0..1..2..etc].movementGoal.
Although the project is not real time, ie I will want to just "step" through it in the end, I do want simultaneous movement to occur. This means that my standard method of iterating through the list will not work as I need information about the other Gladiator's movement decisions in order to figure out any one Gladiator's actual movement as these decisions interact.
How can I access another specific gladiator's variables when I am outside the class and only have them in List form?
Edit:
I guess I could iterate through and test for a variable gladiatorNumber to be correct, then when it is pull that info? That would be pretty round-about but its all I can think of.
Edit2:
As requested, some code. My method in Ai class looks like this:
public void moveAI(List<Gladiator> gladiators) {
My gladiator is defined as such:
public class Gladiator {
Gladiator class is created as an array then added into a list in a separate main class. I don't really want to include more code than this, as there is a ton of it. Basically it boils down to how can I call gladiator[0] from AI class even though I created said object in the main class and only have them in list form in the AI class. Assume all variables in Gladiator are public. The error I am getting is cannot find symbol referring to gladiator[0...1...2...etc].
I think your problem boils down to wanting to pass the arrays of gladiators to another class. That should be fairly easy. If you in your main-class have these two defintions (note you only need one, I recommend the list as it is more versatile, arrays have fixed-length).
You want something like this:
public class Main {
// ....stuff
// This is the main class that keeps the list of gladiators
private List<Gladiator> gladiatorsList;
private Gladiator[] gladiatorsArray;
private MovementAI movementAI;
public Main() {
// You initialize gladiatorsList and gladiatorsArray as before
// gladiatorsList = ...
// gladiatorsArrray = ...
// Now you want to pass this list/array to another class (the AI), you
// can do this in the constructor of that class like so:
movementAI = new MovementAI(gladiatorsList);
}
// ...stuff as before
}
The AI
public class MovementAI {
private List<Gladiator> gladiators;
// Giving the class the list-reference, this list will be the same as the
// list in main, when main-list changes so does this one, they point to the
// same list-object, so the reference is only needed once.
public MovementAI(List<Gladiator> gladiatorsList) {
this.gladiators = gladiatorsList;
}
// The class already has a reference to the list from its constructor so it
// doesn't need the list again as a parameter
public void moveAI() {
}
// If you don't want to keep a reference to the list in this class but only
// use it in a method (I would not recommend this)
public MovementAI() {
}
// You need to pass it gladiatorsList everytime you call this method.
public void moveAI(List<Gladiator> gladiators) {
}
}
I see in your last comment that you have decided to let the AI decide to repaint if it meets a criteria, that is not recommended, you should keep responsibilities separate in your classes, less error-prone and better development. It is recommended to let the AI change the list of gladiators (move them, kill them etc) and the rendererclass simply paint every gladiator.
It also seems you want to have every gladiator be able to hold another gladiator as a target, it is better for them to hold the target as an Object, this way you don't have to search the entire list to find out which gladiator the gladiatornumber refers to and you don't have to think about ordering in the list. Something like this:
public class Gladiator {
// ..other stuff
private Gladiator target;
public Gladiator getTarget() {
return target;
}
public void setTarget(Gladiator target) {
this.target = target;
}
}

Categories

Resources