Initializing static class members - some clarification please - java

I'm a bit of a novice with java and I would appreciate some clarification on when static class variables need to initialized. It a bit much to insert the code I have, so let me break it down to the essential elements. I have an object that performs a particular task. This task requires a number of parameters to be set. These parameters would ideally be static as any instance of the class would use the same parameters. The object is basically a robot that automates a task. The first instance of the robot must be "trained" to do the task (guided by user input). In this "training" it learns a few key parameters and, from those, calculates others that are needed (via a private method). The key parameters are then saved to file to be used by other instances and with subsequent runs of the program (i.e. training is done once only).
The code is structured something like this...
public class Master {
static int[] keyPara;
static int[] otherPara;
public Master() {
/* some defining stuff */
}
void doGuidedTask() {
/* some stuff that calls private methods, etc */
}
void doTask() {
/* some stuff that calls private methods etc */
}
void calcOtherPara() {
/* method to calculate other parameters given key parameters */
}
void saveKeyPara() {
/* method to save key parameters to File */
}
}
The question is what is the proper/best way to initialize these parameters in code? keyPara are determined by implementing the doGuidedTask method, and otherPara are found using the calcOtherPara method. After a single implementation of doGuidedTask, saveKeyPara can be invoked to save them to file and can be read in for subsequent runs of the application program.
I could use a static initialization block: test if the file exists, if so load the key parameters. Not sure if this is allowed because it will require the use of the calcOtherPara method to determine the other parameters i.e. its using a class method in the initialization. Even the read in keyPara would be best implemented as a method (with an eye for future development of the code). The same problem arises if I use the same approach in the constructor - I read elsewhere in the forum that using methods within the constructor is not recommended (not sure I understood why exactly).
I read the tutorial on static variables but it really was not clear to me exactly when they need to be defined and what I should be doing in this case. Any advice here would be appreciated.

public class Master {
static boolean initialised=false;
static int[] keyPara;
static int[] otherPara;
public void doTask() {
if (!initialised)
{
boolean filefound=false;
// put here code to check if your saved file exists
if(filefound)
{
loadkeyfile();
calcOtherPara();
initialised=true;
doAutomatedTask();
} else {
doGuidedTask();
saveKeyPara();
calcOtherPara();
initialised=true;
}
} else {
doAutomatedTask();
}
}
private void doAutomatedTask() {
// put your non-interactive version here
}
}

You should use a static method to initialize static variables.
You can call this static method from the static initializer of the class.
static {
staticMethodThatInitializesStaticMembers ();
}

It appears that are trying to implement something before your object model design is complete. You may have the following objects: Robot (the thing that performs a task); Task (the thing to be performed); TaskStrategy (how to perform the task .. the item you talk about having guided and calculated parameters). You will need to determine whether your task strategies are by task or by robot, and including a reference to a TaskStrategy object in the appropriate class. You may want a TaskStrategyLibrary that handles the task strategies from initial creation through successive learning cycle. With a factory class you can get the appropriate task strategy for a robot (strategy = TaskStrategyLibrary.getStrategy(Robot, Task); and have the TaskStrategy class handle "parameter" changes and update of base strategy.

For this example, I would recommend initializing them when you declare them. So for example, you'd do this:
static int[] keyPara = {1, 2, 3, 4}; //put your array here
static int[] otherPara = {1, 2, 3, 4}; //put a different (or the same) array here

Related

Java: How to test void add, delete and change methods?

I have a few Management classes that are used for search methods, add, change and delete methods, print in table format method and write map to file method. The classes also have a container each as an attribute. Lets say there is a class X. This would be the class XManagement, and its container has objects of class X.
search() method returns the object of X, but first it gathers its ID via input.
add() method gathers input data for the creation of an object X, and the very last line of its code is for adding that object to its container.
change() method first searches for the object the user wants to change (via search() method), and then gathers data and changes the object via setter methods. It then calls the write() method for re-writing the file.
delete() method searches for the object (via search()), and then just removes it from its container, after which it calls the write() method.
The write() method is also void. It goes through the container for each object, and its data is then appended to a parse-able String, which is written to file.
Here are the examples:
public class XManagement {
protected Hashtable<Integer, X> xes = new Hashtable<>();
public XManagement(String fileName) {
// Constructor.
// Loads the input file, then parses it.
// Once parsed, the objects of X class are created.
// They are then put into the container (xes).
}
protected X search() {
// Both generic methods.
Integer uuid = enterInteger("ID");
return (X) find(uuid, xes);
}
public void add() {
Integer uuid = UUID(xes); // Generic method, generates UUID.hashCode()
// and checks for duplicates.
String a = enterString("Name");
Date d = enterDate("Start");
// ...............
X x = new X(uuid, a, d, etc);
xes.put(x.getID(), x);
write();
}
public void delete() {
X x = search();
xes.remove(x.getID(), x);
write();
}
public void change() {
X x = search();
String a = enterString("Name");
x.setA(a);
Date d = enterDate("Start");
x.setD(d);
// .......................
write();
}
protected void write() {
File file = new File("x.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(file));
String curr = "";
for (int id : xes.keySet()) {
curr += xes.get(id).getA() + "|" + xes.get(id).getD() + "|"; // etc
}
out.write(curr);
// There's, naturally, try/catch/finally here. For the sake of simplicity, I left it out here.
}
}
Class X goes like this:
public class X {
String a;
Date d;
// etc
public X(String a, Date d) {
this.a = a;
this.d = d;
}
// Getters and setters.
}
It's a lot more complicated than that, I just tried to keep it simple here to get some help - I'll try to figure out the harder stuff when I get the basics.
In some management classes, methods and constructors have the instances of other Management classes as their input parameters, so that they can call their methods inside, because most of them are connected. Let's say the Y class has X as an attribute, and when I create a Y object in YManagement add() method, I need to be able to choose one from all the available X objects from xes, via the search() method contained in XManagement.
I decided to keep it simple for now, but if you want, you can tell me how to approach testing where I'd have instances of other Management classes as an input.
How do I write detailed JUnit 5 test cases for these methods?
Sorry if I made a mistake somewhere in the code, I haven't copied it but written in here, generalizing the stuff that gets repeated in other Management classes.
If you have any other suggestions, as to the code itself, feel free to write that.
These methods are hard to test because they're doing too much. You have input, output to files, and data modifications.
Let's look at this method:
protected X search() {
// Both generic methods.
Integer uuid = enterInteger("ID");
return (X) find(uuid, xes);
}
Why do you call enterInteger when you could pass the desired ID into the method as a parameter? Let the client tell your class which ID to search for. Now the search is doing one thing: looking up a reference in the map.
I think that naming a class X gives no information whatsoever about what it's for. I'd prefer something that gives me a hint - better readability. You abstract all information out of the code with this naming scheme. Good names matter. Think harder about this one.
Your XManagement class looks like a simplistic in-memory database. Have you thought about using something that would allow you to use SQL? Maybe H2 would be a better choice. If this class were interface based you could swap out the implementation and clients would not have to change.
A better design would partition responsibility out to separate classes. For example, your data object could be accompanied by an interface-based persistence tier that would handle searches, updates, persistence, etc.
When I find that methods are too hard to test, it's usually a sign that the class needs to be redesigned. Hard to test is the same thing as hard to use for clients.
I'd replace your XManagement class with an interface:
package persistence;
public interface Repository<K, V> {
List<V> find();
V find(K id);
List<V> find(Predicate<V> filter);
void save(V v);
void update(V v);
void delete(K id);
void delete(V v);
}
You'll have an instance for each one of your Shows, Performances, Tickets, Users, etc.
package persistence;
public class ShowRepository implements Repository<Integer, Show> {
// TODO: You'll need a constructor and a Map for Shows.
public List<Show> find() { // the rest for you }
public Show find(Integer id) { // the rest for you }
public List<Show> find(Predicate<Show> filter) { // the rest for you }
public void save(Show v) { // the rest for you }
public void update(Show v) { // the rest for you }
public void delete(Integer id) { // the rest for you }
public void delete(Show v) { // the rest for you }
}
Much better than your X, in my opinion.
If you write your class using my interface there won't be any console interaction in those classes. Everything it needs is passed in by callers.
You can create separate concrete implementations for an in-memory cache, a relational or NoSQL database that each implement this interface.
You need to redesign your code as current implementation is untestable. I suggest following steps:
break your code to more cohesive classes;
extract interfaces;
use dependency injection for provided classes;
use parametrized methods;
After that you will be able to test your class with mocked dependencies or fake objects. Check out SOLID principles as if you follow them your code will be testable and maintanable.
You question is rather broad.
So, I will focus on the essential.
1) How to test void methods ?
A void method doesn't return any result but it creates side effect on the underlying object/system.
So you have to assert that the void method does what it is designed to do by asserting that the expected side effect is effective.
For example your add() method adds the object in the HashTable (you should rather use a HashMap or a ConcurrentHashMap if you have race conditions), so you should check that the object was correctly added.
You could for example have a search() method that return an object if it is contained. And by using it you could check if the object was added :
X x = ...;
xManagement.add(x);
X actualX = xManagement.search(x.getId());
assertEquals(x, actualX)
To do it, you have to make evolve your actual class that actually doesn't provide a simple retrieval method.
2) How to test classes that have dependencies with other classes ?
Unit tests of a class should be done in isolation of other classes.
So if YManagement methods have to invoke methods of XManagement, you should mock XManagement dependency and record a behavior for it.
Don't test twice the same thing.

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.

Java: most efficient way of changing method arguments

I have a problem. So, assume there is this class native to the JRE with 100+ methods:
class HundredMethods {
public void method1(int) {
}
public void method2(int) {
}
... (98 more methods)
}
and I want to alter the arguments of 5 of those methods. Specifically, integers to doubles. and add an extra double argumentMy current solution involves a wrapper class that:-A: Provides direct access to the original class
-B: Has five methods that "translate" double arguments (with some extra inputs) into the integer arguments of the original. So:
class WrapperMethods{
public HundredMethods original = (assigned at constructor)
public void method1(double,double(extra)) {
int i = (assigned a value in "code" below)
this.original.method1(i);
}
}
Is there another lightweight solution to both changing and adding arguments to a few methods in a "heavy" class besides the one above? In terms of actually implementing this solution in my code, I've found that it can get messy when a user doesn't know what methods the wrapper class changes. In fact, I have a roughly 250+ method class that I'm changing 25 methods of, so the bigger the class, the messier my code becomes. Considering that I want to publish my code as public, someone would have to look up what methods the wrapper changes every time they wanted to use the wrapper.
Thanks!
You can make a subclass and add in 2 methods for each of the five methods that you want to modify. One that takes a double, that does your logic and does a super. invocation to the original method, and one that takes an int and makes sure that it does the same thing as when you pass in a double.
All the other 95 methods will still be accessible through your subclass as normal.
class WrapperMethods extends HundredMethods {
public void method1(double d) {
int i = (assigned a value in "code" below)
super.method1(i);
}
public void method1(int i) {
// Make sure that any calls that happen to pass in an integer,
// also go by your logic.
this.method1((double)i);
}
}

Java unit testing: the easiest way to test if a callback is invoked

I often work with methods that accept callbacks, and callbacks seem to be somewhat hard to test. Let's consider the following scenario, if there's a method that accepts a callback with a single method (for simplicity, I assume the testing method is synchronous), the following boilerplate could be written just to ensure that a callback method is invoked:
#Test
public void testMethod() {
final boolean[] passed = {false};
method(new Callback() {
#Override
public void handle(boolean isSuccessful) {
passed[0] = isSuccessful;
}
});
assertTrue(passed[0]);
}
It looks like a surrogate. I would like to know: is there a more elegant way to test such code to make the code above look more like the pseudo-code below?
#Test
public void testMethod() {
// nothing explicit here, implicit boolean state provided by a test-runner
method(new Callback() {
#Override
public void handle(boolean isSuccessful) {
if ( isSuccessful ) {
pass(); // not sure how it should look like:
// * an inherited method that sets the state to "true"
// * or an object with the pass method
// * whatever
// but doesn't exit testMethod(), just sets the state
}
}
});
// nothing explicit here too:
// test runner might check if the state is changed to true
// otherwise an AssertionError might be thrown at the end of the method implicitly
}
A little cleaner. Is it possible in JUnit, TestNG or any other testing framework? Thanks!
UPDATE
Sorry, I seem to have asked a vague question that doesn't really meets what I wanted to ask. I basically meant any code (not necessarily a callback) that might be invoked if certain conditions are satisfied just to set the result state to true. Simply speaking, I just want to get rid of the initial boolean[] passed and the final assertTrue(passed[0]) assuming that they are some kind of prologue and epilogue respectively and assuming that the initial state is set to false so the pass() should be invoked to set the state to true. No matter how the passed[0] is set to true, no matter where from. But unfortunately I have asked this question using the context of callbacks, however this is just an option, not a requirement. Thus the title of the question does not reflect what I really wanted to ask, but before the update some answers have been posted.
This is typically what a mocking framework can do for you.
With Mockito for instance:
// imports ommited for brevity
#Test
public void callbackIsCalled()
{
final CallBack callBack = mock(CallBack.class);
method(callBack);
verify(callBack, only()).handle(any());
}
Of course, this is an example of verification mode (only()) and value matcher (any()). You can do more...
(other mocking frameworks exist, but I personally find Mockito the easiest to use, in addition to being one of the most powerful)
Given that this is the sort of thing you're likely to need in several places, I would just create a named class to use for tests:
public class FakeCallback implements Callback {
private boolean wasSuccessful;
private boolean handleCalled;
#Override public void handle(boolean isSuccessful) {
this.wasSuccessful = isSuccessful;
handleCalled = true;
}
// Getters for fields above
}
You can then use something like:
// Arrange...
FakeCallback callback = new FakeCallback();
// Act...
method(callback);
// Assert
assertTrue(callback.wasHandleCalled());
assertTrue(callback.wasSuccessful());
You could absolutely use a mocking framework for this instead, but personally I find that often it's simpler to create a single fake implementation than set up mocks repeatedly. Both ways will work though.
Give list::add as callback
When the task is to test a callback that is a functional interface accepting one parameter (here a boolean, could as well be String or any random type), it seems most concise to prepare a list, pass the List.add(e) method as callback and then check the content of the list:
List<Boolean> callbackArgs = new ArrayList<>();
methodUnderTest(callbackArgs::add);
// assert that the callback was called exactly once and with a "true" value:
assertEquals(Arrays.asList(true), callbackArgs);
Alternative case for a callback that accepts Strings:
List<String> callbackArgs = new ArrayList<>();
methodUnderTest(callbackArgs::add);
// assert that the callback was called twice with "foo" and "bar" values respectively:
assertEquals(Arrays.asList("foo", "bar"), callbackArgs);
Analogously, a counter class may serve for testing a callback that accepts no parameter. Here using AtomicInteger, as that seems to be the only counter-like class available in the standard libs - the atomicity property is not needed here:
AtomicInteger callbackCounter = new AtomicInteger();
methodUnderTest(callbackCounter::incrementAndGet);
// assert that the callback was called 5 times:
assertEquals(5, callbackCounter.get());

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