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.
Related
I need help !. I am trying to access the value of a static variable from one class in another class in an android project. This is the static class...
public class NamesStore {
private static NamesStore sNamesStore ;
private static List<Name> sNames = new ArrayList<>();
public static NamesStore getInstance() {
if (sNamesStore == null) {
return new NamesStore();
} else {
return sNamesStore;
}
}
public List<Name> getNames(){
return sNames;
}
}
now in other class, I try to get the static variable to use the value but modifying it before use like this ...
public class Utils{
public static removeTheseNamesFromTheGeneralNames(List<Name> namesToBeRemoved){
List<Name> names = NamesStore.getInstance().getNames();
names.removeAll(namesToBeRemoved);
return names;
}
}
when I call the method removeTheseNamesFromTheGeneralNames, the static variable in NamesStore is also modified and I can't figure out why.? Is this a normal behavior of a static field? and if so, please how can I copy the value of a static field and modify without changing the value stored in the static field.? I could make it static and final to resolve this but I also need to set that static variable from time to time with a setter method. Thanks for the help in advance.
'static' is not really the core problem here (though it might contribute). The problem is in method getNames() and how the result is used by its caller.
In your NamesStore class, there is one list of names (the ArrayList) and there is one reference to that list of names (sNames).
When you execute return sNames and the caller assigns the return value to his variable names, you still have exactly one list of names (one ArrayList), now with two references to the same list. This is not a consequence of 'static' but a consequence of how Java uses reference types; in short, assignment (and returning a value) makes a copy of a reference, it does not make another instance of the thing being referred to.
So, of course, when the list referred to by names is modified, that does modify the one and only list of names that exists.
If you wish to allow the caller to modify the list returned by your getNames() method without modifying your list, then you need to return a copy of your list, not your list itself.
Writing return new ArrayList<>(sNames) would do that; but note that only the list of names is copied, whatever is in the list is (presumably 'names') is not. In other words, if your caller modifies an actual name, it will modify the only instance of that name. You need to determine what your requirements are.
An alternative approach is to forbid your user from changing the returned list; that can be implemented as return Collections.unmodifiableList(sNames). If an attempt is made to change that list then the code doing that change will fail. Anyone who wants to modify the list (as in your example) must make themselves a copy first.
The decision between these two is probably made on the basis of considering how many users of getNames() expect to modify the result. If that is not the usual case, then making those users do the copying is generally the better approach.
I think is better to read about class members first, to understand how it works. https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
My advice is to refactor the code in this way:
public class NamesStore {
private static NamesStore sNamesStore = new NamesStore();
private List<Name> sNames = new ArrayList<>();
private NamesStore(){}
public static NamesStore getInstance() {
return sNamesStore;
}
public List<Name> getNames() {
return Collections.unmodifiableList(sNames);
}
public List<Name> getNamesWithout(List<Name> namesToBeRemoved) {
return sNames.stream().filter(name -> !namesToBeRemoved.contains(name)).collect(Collectors.toList());
}
}
EXPLANTION ABOUT FILTER METHOD
The method getNamesWithout(List namesToBeRemoved) can be written also in this way:
public List<Name> getNamesWithout(List<Name> namesToBeRemoved) {
return sNames.stream().filter(new Predicate<Name>() {
#Override
public boolean test(Name name) {
return !namesToBeRemoved.contains(name);
}
}).collect(Collectors.toList());
}
The interface Predicate, has a single abstract method (a single method that you have to implement in subclasses). In Java, an interface with a single abstract method is called functional interface. When you have to implement a functional interface, you can use lambda expression. What does't mean this: you can omit the boilerplate code and to keep only what is important. In the below picture, the important code is marked in green and the boilerplate code in red.
I hope that my explanation clarifies you what is with that name from the lambda expression.
Say I have a class, Bobject with an instance variable and method to retrieve it:
public class Bobject {
private int bInstVar;
public Bobject() {
bInstVar = 1;
}
getBInstVar() {
return bInstVar;
}
}
If I create a class Cobject representing an object that is an array of Bobject like so:
public class Cobject {
public Bobject[] cInstVar;
public Cobject() {
cInstVar = new Bobject[2]; //arbitrary array size for simplicity of the question
for (i = 0; i <= 2; i++;) {
cInstVar[i] = new Bobject();
}
}
}
If I have a main program that creates a Cobject and attempts to access methods of the references to the Bobjects stored in each element, I find that I have to first access the Cobject instance variable, cInstVar. This means cInstVar has to be public for main() to get at it without a method if main is outside of the package or class.
My question is, is there a way around doing this:?
Cobject c = new Cobject;
c.cObject1[0].getBInstVar();
Instead, I want to have an object that is an array of another class and get to that classes instance methods easier like so:
Cobject c = new Cobject;
c.getBInstVar(); // error says 'array required, but Cobject found'
I'm still pretty new to Java (and stackExchange) so please forgive me if anything I've presented is unclear. Thanks in advance!
As a general rule of thumb class variable should be declared as private and you should use getter and settle methods....
Meaning you will need to create a getter method in 'Cobject' to get the 'Bobject' object your after.... Then another getter/setter method to access any attributes there, or a method to manipulate any data
But yes, you could hard code a method that will go into the array and return what you ask for. Probably need an index parameter tho
you can create a getter method for Bobject[] in Cobject class
and then you can do c.getCObject1()[0].getBInstVar();
I have a very weird situation. I have a class that has a couple of members, like this:
public class myMainClass
{
public aClass myObject = new aClass();
private int numberOfUpdates = 0;
public anotheClass.memberClass anotherObject = new anotheClass.memberClass();
Note that the anotherClass has a class defined within it. (Not sure if that enters into the problem I'm having).
Both aClass and anotheClass.memberClass have a member with the same name, ThisMember.
I also have a method within myMainClass that does some modifications to the members of the myMainClass object:
public void Update(double aPassedInNumber)
{
anotherObject.ThisMember = aPassedInNumber;
//etc
}
I'm only modifying that one member. However, when I do that, myObject.ThisMember also gets modified to the same value! It's as though (??) both member variables occupy the same location in memory. Or that one is somehow a reference to the other.
It's as if I had done:
public void Update(double aPassedInNumber)
{
anotherObject.ThisMember = aPassedInNumber;
myObject = aPassedInNumber;
//etc
}
BUT I'M NOT. I'm only doing the first assignment, yet both of those variables get modified.
I've traced this and printed out diagnostics and used a watch window and it clearly modifies both variables.
How can that be? What am I doing wrong? How can I fix it?
Oh, man. It looks like I still don't have a handle on the reference concept in JAVA. That one variable is indeed simply a reference to the other object.
Now it seems I have to implement a copy method for the class.
Aaaargh!!
I'm trying to implement a simple spreadsheet using Java. It interacts with the user through some menus on the console, and a user can import a given file with some pre-made info about the spreadsheet to be created (lines, columns, and content of cells).
I am trying to make a static class which I called Parser, and the goal of this class is to break down each line of the import into little pieces so I can then apply the correct methods to them (read the cell to which content is being added, and what type of content am I trying to add).
I made my Parser static, because I want to use it without the need of instantiating a new object every time I need it (is this correct?). I have a specific method that is giving me trouble though. Whenever I receive input like this: 1;1|=2;3it means that my cell 1;1 references the cell 2;3. I am telling the parser to return a new Reference(getCell(i,j)). This is because my Reference class constructor receives a Cell, but of course the java compiler tells me I cannot use a non-static method, which is the case of the getCell, inside that static class.
So my question is: is there any way to overcome this problem? Any way to use a non-static method in a static class or should I instantiate a new Parser object when I try to read an import file?
It might be helpful to see some of your code to determine which method is more appropriate, but as this is a common pitfall in object oriented design, I'll try to answer the question generically.
If you define something as static, that means it has no association with any instances, even though it shares the class name. For instance,
public class Table {
List<Cell> cells;
public Table() {
while (someCondition)
parseInput(nextInput);
}
public Cell getCell(int i, int j) {
...
}
public static Cell parseInput(String input) {
Cell cellToReturn = new Cell();
...
if (input.references(cell)) cell = getCell(i,j); //Error here!
...
return cellToReturn;
}
}
The problem arises because the parseInput method is static, and yet it is referencing a specific instance's list of cells! Which one is it referencing? Who knows!
You can solve the issue two ways:
1: Make the parser non-static: public Cell parseInput(String input) {
2: Pass the table to the parser, so it knows what to reference:
public static Cell parseInput(String input, Table target) {
Cell cellToReturn = new Cell();
...
if (input.references(cell)) cell = target.getCell(i,j); //No more error!
...
return cellToReturn;
}
Now, as you stated, the parser is a class, not just a method. But the general rule still applies. You cannot reference an instance field from a static method, because that static method is not associated with any instance!
I made my Parser static, because I want to use it without the need of instantiating a new object every time I need it (is this correct?).
Maybe, but not for the reason you state. Why don't you want to create an instance of your class? If that's your only reason for making it static, then it's not a very relevant one. Indeed, something like the Singleton Pattern essentially achieves the same thing, ensuring that you don't have to keep creating an instance, because there's always exactly one instance to use.
If your object is exactly that... an object, then it should probably be modeled as an instance. I generally tend to think of things which are objects as non-static by nature and things which are concepts about an object are more static by nature.
Let's use the belabored OO example of cars for a moment. If I want to know the price of a car, that's a property of a particular car. I'd have to specify an instance of an Accord for example in order to query it for that property. If, on the other hand, I want to know the average price for a particular model, that's more of a static concept. I'm not talking about any particular instance of Accord, just Accords in general. So where something like getPrice() would be an instance method on Car, something like getAveragePrice() might not.
should I instantiate a new Parser object when I try to read an import file?
Is that such a bad thing?
Now, for the problem at hand, which reference specifically is the compiler complaining about? I guess I'm having trouble picturing it, can you provide a simplified code example so I can see how these static and non-static classes/members relate? Essentially you can reference instance members from a static location, you just need to reference an instance in order to do it. Taking my belabored example above, I can't do this:
class Car {
int getPrice() {
return 20000;
}
static int getAveragePrice() {
return Car.getPrice();
}
}
But I can do this (albeit probably ill-advised in this overly-contrived example):
class Car {
int getPrice() {
return 20000;
}
static int getAveragePrice() {
var someRandomCar = new Car();
return someRandomCar.getPrice();
}
}
If your static method need access to non-static methods (without instantiating anything or accessing instance directly), then MUST be defined as non-static.
private static Parser INSTANCE = new Parser();
public static Parser getInstance() {
return INSTANCE;
}
...
public void nonStaticMethod() {
Parser parser = Parser.getInstance();
parser.whateverParserMethodYouWant();
}
Editing to make this more clear:
class Parser {
private Parser() {}
private static Parser INSTANCE = new Parser();
public static Parser getInstance() {
return INSTANCE;
}
}
...
class ParserClient {
...
public void nonStaticMethod() {
Parser parser = Parser.getInstance();
parser.whateverParserMethodYouWant();
}
}
I am practicing inheritance.
I have two similar classes that I'd like to assimilate into one array, so I thought to use the Object class as a superclass since everything is a sublcass of Object.
So, for example I put T class and CT class into an array called all like so:
Object all[] = new Object[6];
all[0] = T1;
all[1] = CT2;
all[2] =T3;
all[3] = CT1;
all[4] = T2;
all[5] = CT3;
I skipped the declarations as thats not my problem.
My real issue becomes when I wish to call a function within the array utilizing a loop:
for (int i = 0; i < 6; i++) {
all[i].beingShot(randomNum, randomNum, AK47.getAccuracy());
}
The classes involved with T and CT respectively both have the beingShot method, which is public.
Eclipse advises casting them as a quick fix. I'm wondering if there is any logical alternative other than creating my own Object class that holds the beingShot method, or adding this to the class of Object, although I feel either of these choices would cause more problems in the long run.
Thanks!
If both classes implement the same method(s), you should consider creating an interface.
Interfaces are very powerful and easy to use.
You could call your interface Shootable.
You can create an array of different objects that implement Shootable and treat them all the same.
// Define a VERY simple interface with one method.
interface Shootable {
public void beingShot();
}
// Any class that implements this interface can be treated interchangeably
class Revolver implements Shootable {
public void beingShot() {
System.out.println("Revolver: firing 1 round");
}
class MachineGun implements Shootable {
public void beingShot() {
System.out.println("Machine Gun: firing 50 rounds");
}
}
class HockeyPuck implements Shootable {
public void beingShot() {
System.out.println("Hockey Puck: 80 MPH slapshot");
}
}
class RayBourquePuck implements Shootable {
public void beingShot() {
System.out.println("Hockey Puck: 110 MPH slapshot");
}
}
class OunceOfWhiskey implements Shootable {
public void beingShot() {
System.out.println("Whiskey Shot: 1 oz down the hatch...");
}
}
// You can declare an array of objects that implement Shootable
Shootable[] shooters = new Shootable[4];
// You can store any Shootable object in your array:
shooters[0] = new MachineGun();
shooters[1] = new Revolver();
shooters[2] = new HockeyPuck();
shooters[3] = new OunceOfWhiskey();
// A Shootable object can reference any item from the array
Shootable anyShootableItem;
// The same object can to refer to a MachineGun OR a HockeyPuck
anyShootableItem = shooters[0];
anyShootableItem.beingShot();
anyShootableItem = shooters[2];
anyShootableItem.beingShot();
// You can call beingShot on any item from the array without casting
shooters[0].beingShot();
shooters[1].beingShot();
// Let's shoot each object for fun:
for (Shootable s : shooters) {
s.beingShot();
}
Here's a great related question and answer.
Object doesn't have the method beingShot. If all of the objects in array are of the same class, then your array should be of that same class. Otherwise they all should have same interface implemented or extend the same class. I can't imagine why would you want explicitly extend Object here, it doesn't add any functionality whatsoever.
You need to typecast your object references to appropriate class to call their method..
For each reference you fetch from your array, you need to check using instanceof operator, of which is the instance referred to by your object reference.. Accordingly you can typecast the reference to that class..
But Typecasting is an ugly thing.. You should avoid it as far as possible.. If you have to choose which method to invoke based on exact sub class, you should probably go with an Interface.. It is the best way you can achieve what you want here...
And I think you have got enough information about how to implement it..
You cant do it...since Java does not support extension method. (C# does)
READ THE LINK BELOW:
Java equivalent to C# extension methods